├── .github └── FUNDING.yml ├── README.md └── MagicCopy.ps1 /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [p3nt4] 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MagicCopy 2 | Powershell script to exfiltrate large files quickly and securely. 3 | 4 | Files are split into multiple pieces and encrypted using AES. Multithreading is supported for increased copy speed. 5 | 6 | 7 | ### Magic-Put 8 | 9 | Store file to a remote or local location. 10 | 11 | ``` 12 | Magic-Put -PieceSize 10MB -File 'C:\MYBIGFILE.DATA' -Destination 'O:\' -Key "Password" -Threads 20 13 | ``` 14 | 15 | Recover lost pieces: 16 | 17 | ``` 18 | Magic-Put -PieceSize 10MB -File 'C:\MYBIGFILE.DATA' -Destination 'O:\' -Key "Password" -FirstPiece 20 -LastPiece 25 19 | ``` 20 | 21 | ### Magic-Get 22 | 23 | Recover file: 24 | 25 | ``` 26 | Magic-Get -File 'O:\MYBIGFILE.DATA' -Destination 'C:\' -Key "Password" 27 | ``` 28 | 29 | 30 | ### Sources 31 | 32 | https://gallery.technet.microsoft.com/scriptcenter/EncryptDecrypt-files-use-65e7ae5d 33 | https://gallery.technet.microsoft.com/scriptcenter/Powershell-functions-to-cb6bb05a 34 | -------------------------------------------------------------------------------- /MagicCopy.ps1: -------------------------------------------------------------------------------- 1 | Function Magic-Put([STRING] $File, [STRING] $Destination, [int] $PieceSize = 10MB, [STRING] $Key, [int] $FirstPiece = 1, [int] $LastPiece = 10MB, [int] $Threads = 1){ 2 | [ScriptBlock] $ScriptBlock = { 3 | param([Byte[]]$BUFFER,[String]$path,[String]$Key,[int]$BYTESREAD) 4 | try{ 5 | $Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create('AES') 6 | $Crypto.KeySize = 256 7 | $Crypto.Key = New-object System.Security.Cryptography.SHA256Managed | ForEach-Object {$_.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Key))}; 8 | $FileStreamWriter = New-Object System.IO.FileStream($path, [System.IO.FileMode]::Create); 9 | $Crypto.GenerateIV() 10 | $FileStreamWriter.Write([System.BitConverter]::GetBytes($Crypto.IV.Length), 0, 4) 11 | $FileStreamWriter.Write($Crypto.IV, 0, $Crypto.IV.Length) 12 | $Transform = $Crypto.CreateEncryptor(); 13 | $CryptoStream = New-Object System.Security.Cryptography.CryptoStream($FileStreamWriter, $Transform, [System.Security.Cryptography.CryptoStreamMode]::Write); 14 | $CryptoStream.Write($BUFFER, 0, $BYTESREAD); 15 | $CryptoStream.FlushFinalBlock(); 16 | }catch{} 17 | Finally{ 18 | if($FileStreamWriter){$FileStreamWriter.Close()}; 19 | if($CryptoStream){$CryptoStream.Close()}; 20 | } 21 | } 22 | try{ 23 | $ErrorActionPreference = "Stop" 24 | "Source: $File"; 25 | "Destination: $Destination"; 26 | "Split Size: $PieceSize"; 27 | "Threads: $Threads"; 28 | $FileStreamReader = New-Object System.IO.FileStream($File, [System.IO.FileMode]::Open) 29 | $FILEPATH = [IO.Path]::GetFullPath($Destination); 30 | if ($FILEPATH -ne "") { $FILEPATH = $FILEPATH + "\";} 31 | $FILENAME = [IO.Path]::GetFileNameWithoutExtension($File); 32 | $EXTENSION = [IO.Path]::GetExtension($File); 33 | [Byte[]]$BUFFER = New-Object Byte[] $PieceSize; 34 | [int]$BYTESREAD = 0; 35 | $NUMFILE = $FirstPiece; 36 | $FileStreamReader.Position = ($PieceSize * ($FirstPiece - 1)); 37 | while (($BYTESREAD = $FileStreamReader.Read($BUFFER, 0, $BUFFER.Length)) -gt 0){ 38 | if($NUMFILE -eq $LastPiece + 1){ 39 | break; 40 | } 41 | "[$NUMFILE] Reading $BYTESREAD bytes of $File"; 42 | $NEWNAME = "{0}{1}{3}{2,2:00}.AES" -f ($FILEPATH, $FILENAME, $NUMFILE, $EXTENSION); 43 | if($Threads -eq 1){ 44 | Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $BUFFER,$NEWNAME,$Key,$BYTESREAD; 45 | } 46 | else{ 47 | [Byte[]]$BUFFER2 = New-Object Byte[] $PieceSize; 48 | $BUFFER.CopyTo($BUFFER2,0); 49 | while (@(Get-Job -State 'Running').Count -ge $Threads){ 50 | Start-Sleep -m 50; 51 | } 52 | Start-Job -ScriptBlock $ScriptBlock -ArgumentList $BUFFER2,$NEWNAME,$Key,$BYTESREAD | Out-Null; 53 | } 54 | ++$NUMFILE; 55 | } 56 | }Finally{ 57 | if($FileStreamReader){$FileStreamReader.Close();} 58 | } 59 | } 60 | 61 | Function Magic-Get([STRING] $File, [STRING] $Destination, [STRING] $Key){ 62 | $ErrorActionPreference = "Stop" 63 | $Parts = @(); 64 | $i = 01; 65 | $PartPath = $File + $i.ToString("00") + ".AES"; 66 | while(Test-Path $PartPath){ 67 | $Parts+=$PartPath; 68 | $i++; 69 | $PartPath = $File + $i.ToString("00") + ".AES"; 70 | } 71 | $Path = $Destination + "\" + [IO.Path]::GetFileName($File); 72 | if ((!$Path) -or ($Path -eq "")){ 73 | Write-Error "Target filename missing."; 74 | return; 75 | } 76 | if ($Parts.Count -eq 0){ 77 | Write-Error "No parts found."; 78 | return; 79 | } 80 | $FileStreamWriter = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Create); 81 | $isFirst=$true; 82 | $Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create("AES"); 83 | $Crypto.KeySize = 256 84 | $Crypto.Key = New-object System.Security.Cryptography.SHA256Managed | ForEach-Object {$_.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Key))}; 85 | if ($PSVersionTable.PSVersion.Major -ge 3){ # method CopyTo() is implemented in .Net 4.x first 86 | $Parts | foreach { 87 | "Appending $_ to $Path."; 88 | $FileStreamReader = New-Object System.IO.FileStream($_, [System.IO.FileMode]::Open); 89 | [Byte[]]$LenIV = New-Object Byte[] 4; 90 | $FileStreamReader.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null; 91 | $FileStreamReader.Read($LenIV, 0, 3) | Out-Null; 92 | [Int]$LIV = [System.BitConverter]::ToInt32($LenIV, 0); 93 | [Byte[]]$IV = New-Object Byte[] $LIV; 94 | $FileStreamReader.Seek(4, [System.IO.SeekOrigin]::Begin) | Out-Null; 95 | $FileStreamReader.Read($IV, 0, $LIV) | Out-Null; 96 | $Crypto.IV = $IV; 97 | $Transform = $Crypto.CreateDecryptor(); 98 | $CryptoStream = New-Object System.Security.Cryptography.CryptoStream($FileStreamWriter, $Transform, [System.Security.Cryptography.CryptoStreamMode]::Write); 99 | $isFirst = $false; 100 | $FileStreamReader.CopyTo($CryptoStream); 101 | $FileStreamReader.Flush(); 102 | $CryptoStream.FlushFinalBlock(); 103 | $FileStreamReader.Close(); 104 | } 105 | $CryptoStream.Close(); 106 | } 107 | else 108 | { # .Net 3.5x 109 | [Byte[]]$BUFFER = New-Object Byte[] 100MB; 110 | $Parts | foreach { 111 | "Appending $_ to $Path."; 112 | $FileStreamReader = New-Object System.IO.FileStream($_, [System.IO.FileMode]::Open); 113 | [Byte[]]$LenIV = New-Object Byte[] 4; 114 | $FileStreamReader.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null; 115 | $FileStreamReader.Read($LenIV, 0, 3) | Out-Null; 116 | [Int]$LIV = [System.BitConverter]::ToInt32($LenIV, 0); 117 | [Byte[]]$IV = New-Object Byte[] $LIV; 118 | $FileStreamReader.Seek(4, [System.IO.SeekOrigin]::Begin) | Out-Null; 119 | $FileStreamReader.Read($IV, 0, $LIV) | Out-Null; 120 | $Crypto.IV = $IV; 121 | $Transform = $Crypto.CreateDecryptor(); 122 | $CryptoStream = New-Object System.Security.Cryptography.CryptoStream($FileStreamWriter, $Transform, [System.Security.Cryptography.CryptoStreamMode]::Write); 123 | while ($FileStreamReader.Position -lt $FileStreamReader.Length){ 124 | $BYTESREAD = $FileStreamReader.Read($BUFFER, 0, $BUFFER.Length); 125 | $CryptoStream.Write($BUFFER, 0, $BYTESREAD); 126 | } 127 | $CryptoStream.FlushFinalBlock(); 128 | $CryptoStream.Close(); 129 | $FileStreamReader.Close(); 130 | } 131 | } 132 | $FileStreamWriter.Close(); 133 | } 134 | --------------------------------------------------------------------------------