powershell -sta #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. $url = "https://fiechter365-my.sharepoint.com" $key = "PleaseEnterTheNoSpaceRandomKey" Add-Type -TypeDefinition @" using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Windows.Forms; public static class WININET { private const int INTERNET_COOKIE_HTTPONLY = 0x00002000; [DllImport("wininet.dll", SetLastError = true)] private static extern bool InternetGetCookieEx( string url, string cookieName, StringBuilder cookieData, ref int size, int flags, IntPtr pReserved); public static string url; private static string authCookie; public static string GetCookie(string url, string password) { WININET.url = url; WebBrowser webBrowser = new WebBrowser(); webBrowser.Navigated += WebBrowser_Navigated; webBrowser.ScriptErrorsSuppressed = true; webBrowser.Dock = DockStyle.Fill; webBrowser.Navigate(url); Form form = new Form(); form.WindowState = FormWindowState.Maximized; form.Controls.Add(webBrowser); form.ShowInTaskbar = true; Application.Run(form); return Encrypt(authCookie, password); } private static void WebBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e) { int size = 512; StringBuilder sb = new StringBuilder(size); if (!InternetGetCookieEx(url, null, sb, ref size, INTERNET_COOKIE_HTTPONLY, IntPtr.Zero)) { if (size < 0) { } sb = new StringBuilder(size); if (!InternetGetCookieEx(url, null, sb, ref size, INTERNET_COOKIE_HTTPONLY, IntPtr.Zero)) { } } string cookies = sb.ToString(); if (cookies.Contains("FedAuth")) { authCookie = cookies; Application.Exit(); } } private const int Keysize = 256; // This constant determines the number of iterations for the password bytes generation function. private const int DerivationIterations = 1000; public static string Encrypt(string plainText, string passPhrase) { // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text // so that the same Salt and IV values can be used when decrypting. byte[] saltStringBytes = Generate256BitsOfRandomEntropy(); byte[] ivStringBytes = Generate256BitsOfRandomEntropy(); byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations); byte[] keyBytes = password.GetBytes(Keysize / 8); using (RijndaelManaged symmetricKey = new RijndaelManaged()) { symmetricKey.BlockSize = 256; symmetricKey.Mode = CipherMode.CBC; symmetricKey.Padding = PaddingMode.PKCS7; using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes)) { using (MemoryStream memoryStream = new MemoryStream()) { using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); cryptoStream.FlushFinalBlock(); // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes. byte[] ms = memoryStream.ToArray(); byte[] cipherTextBytes = new byte[saltStringBytes.Length + ivStringBytes.Length + ms.Length]; Array.Copy(saltStringBytes, cipherTextBytes, saltStringBytes.Length); Array.Copy(ivStringBytes,0, cipherTextBytes, saltStringBytes.Length , ivStringBytes.Length); Array.Copy(ms, 0, cipherTextBytes, saltStringBytes.Length + ivStringBytes.Length , ms.Length); memoryStream.Close(); cryptoStream.Close(); return Convert.ToBase64String(cipherTextBytes); } } } } } private static byte[] Generate256BitsOfRandomEntropy() { byte[] randomBytes = new byte[32]; // 32 Bytes will give us 256 bits. RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider(); // Fill the array with cryptographically secure random bytes. rngCsp.GetBytes(randomBytes); return randomBytes; } } "@ -ReferencedAssemblies "System.Windows.Forms" $cookies = ([WININET]::GetCookie($url,$key)) $file = @" powershell -sta #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. "@ $file += "`r`n" + '$key = "PleaseEnterTheNoSpaceRandomKey"'+ "`r`n" $file += 'Add-Type -TypeDefinition @"' + "`r`n" $file += @" using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Windows.Forms; using System.Text.RegularExpressions; public static class WININET2 { [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData); public static void SetCookie(string url, string cookie, string password) { cookie = Decrypt(cookie, password); string pattern = @"(.+?)(?:=(.+?))?(?:;|$|,(?!\s))"; MatchCollection matches = Regex.Matches(cookie, pattern); Dictionary parts = new Dictionary(); foreach (Match match in matches) { string key = match.Groups[1].Value.Trim(); if (!parts.ContainsKey(key)) { parts.Add(key, match.Groups[2].Value); } } InternetSetCookie(url, "FedAuth", parts["FedAuth"] + ";Expires=" + DateTime.Now.AddDays(7).ToString("R")); InternetSetCookie(url, "rtFa", parts["rtFa"] + ";Expires=" + DateTime.Now.AddDays(7).ToString("R")); WebBrowser webBrowser = new WebBrowser(); webBrowser.ScriptErrorsSuppressed = true; webBrowser.Dock = DockStyle.Fill; webBrowser.Navigate(url); Form form = new Form(); form.ShowInTaskbar = true; form.WindowState = FormWindowState.Maximized; form.Controls.Add(webBrowser); Application.Run(form); while (true) ; } private const int Keysize = 256; // This constant determines the number of iterations for the password bytes generation function. private const int DerivationIterations = 1000; public static string Decrypt(string cipherText, string passPhrase) { // Get the complete stream of bytes that represent: // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText] byte[] cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText); // Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes. byte[] saltStringBytes = new byte[Keysize/ 8]; Array.Copy(cipherTextBytesWithSaltAndIv, saltStringBytes, Keysize / 8); // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes. byte[] ivStringBytes = new byte[Keysize / 8]; Array.Copy(cipherTextBytesWithSaltAndIv,Keysize/8, ivStringBytes, 0,Keysize / 8); // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string. byte[] cipherTextBytes = new byte[cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)]; Array.Copy(cipherTextBytesWithSaltAndIv, (Keysize / 8) * 2, cipherTextBytes, 0, cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)); Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations); byte[] keyBytes = password.GetBytes(Keysize / 8); using (RijndaelManaged symmetricKey = new RijndaelManaged()) { symmetricKey.BlockSize = 256; symmetricKey.Mode = CipherMode.CBC; symmetricKey.Padding = PaddingMode.PKCS7; using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)) { using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes)) { using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) { byte[] plainTextBytes = new byte[cipherTextBytes.Length]; int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); memoryStream.Close(); cryptoStream.Close(); return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); } } } } } } "@ $file += "`r`n" + '"@ -ReferencedAssemblies "System.Windows.Forms"' + "`r`n" $file += '([WININET2]::SetCookie("' + $url + '","' + $cookies +'",$key))'+ "`r`n" $msg = @" X-Unsent: 1 MIME-Version: 1.0 Date: 18 Feb 2018 21:24:34 +0200 Subject: Cookie copy to access system Content-Type: multipart/mixed; boundary=--boundary_0_6b9489d3-0e17-4845-a142-6d0e34ee395d "@ $msg += "`r`n`r`n`r`n" $msg += @" ----boundary_0_6b9489d3-0e17-4845-a142-6d0e34ee395d Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable "@ $msg += "`r`n`r`n" $msg += @" Hi "@ $msg += "`r`n`r`n" $msg += @" On the machine where you want to login, please open first Internet Explorer and sign out from O365 (it's required that you are in IE). Afterwards, open the attached textfile, change the key in the firstline with yours and run the copy & paste everything to PowerShell. "@ $msg += "`r`n`r`n" $msg += @" ----boundary_0_6b9489d3-0e17-4845-a142-6d0e34ee395d Content-Type: application/octet-stream; name=run.txt Content-Transfer-Encoding: base64 Content-Disposition: attachment "@ $msg += "`r`n`r`n`r`n" $msg += [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(($file -replace "`n", "`r`n"))) $msg += "`r`n----boundary_0_6b9489d3-0e17-4845-a142-6d0e34ee395d--" New-Item ((Get-Location).Path + "\msg.eml") -type file -force -value ($msg -replace "`n", "`r`n") Start-Process -FilePath ((Get-Location).Path + "\msg.eml")