模仿另外一个用户身份

类别: C#, asp.net 发表评论

最近有个需求,要获取远程服务器上的windows services的状态,不过我的账号没有权限,需要用其他的账户,这就需要模仿另外一个用户的身份。在msdn上找到了个例子,记录下来。

首先,要引入几个win32的api:

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
    int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
 
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
    int SECURITY_IMPERSONATION_LEVEL,ref IntPtr DuplicateTokenHandle);
 
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

LogonUser尝试用一个用户名来登录本机,但不能登录远程机器,如果登录成功的话,将会返回一个句柄。
DuplicateToken复制一个已经存在的Token来创建一个新的access token
CloseHandle关闭一个对象句柄

然后声明如下几个变量/常量

WindowsImpersonationContext impersonationContext;
 
IntPtr tokenHandle = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
 
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
const int SECURITY_IMPERSONATION_LEVEL = 2;
 
tokenHandle = IntPtr.Zero;
dupeTokenHandle = IntPtr.Zero;

之后调用LogonUser来登陆本机并获取句柄

bool returnValue = LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
    LOGON32_PROVIDER_DEFAULT, ref tokenHandle);
// 如果调用失败,则抛出异常
if (false == returnValue)
{
    int ret = Marshal.GetLastWin32Error();
    throw new System.ComponentModel.Win32Exception(ret);
}

复制句柄,其实这步是可以不需要的

bool retVal = DuplicateToken(tokenHandle, SECURITY_IMPERSONATION_LEVEL, ref dupeTokenHandle);
 
if (false == retVal)
{
    CloseHandle(tokenHandle);
    return;
}

模拟用户

// 此处可以用LogonUser返回的tokenHandle, 也可以使用复制的dupeTokenHandle
WindowsIdentity id = new WindowsIdentity(tokenHandle);
WindowsImpersonationContext impersonatedUser = id.Impersonate();
 
// do someting

回复用户,并关闭句柄

// Stop impersonating the user.
impersonatedUser.Undo();
 
// Free the tokens.
if (tokenHandle != IntPtr.Zero)
    CloseHandle(tokenHandle);

参考资料

一个加密解密的小工具

类别: C# 发表评论
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
 
namespace crypt
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            string cleartext = null;
            CryptoHelper cryptoHelper = new CryptoHelper();
 
            if (args.Length < 1)
            {
                Console.Error.Write("Enter string to Encrypt:");
                cleartext = Console.ReadLine();
            }
            else
            {
                if (string.Join("", args).IndexOf("/?") >= 0)
                {
                    showUsage();
                    return;
                }
 
                string clearText = cryptoHelper.Decrypt(args[0]);
                Console.WriteLine(clearText);
                return;
            }
            if ((cleartext != null) && (cleartext.Length >= 1))
            {
                string encryptedText = cryptoHelper.Encrypt(cleartext);
                Console.WriteLine(encryptedText);
            }
 
        }
 
        public static void showUsage()
        {
            Console.WriteLine((((("Crypt is a tool to Encrypt and Decrypt strings\r\n" + "\r\n") + "Usage:\r\n" + "\r\n") + "Crypt alone will invoke the password entering interface\r\n" + "the password will be entered as stars\r\n") + "when you're done the encrypted password will be written to Console\r\n" + "\r\n") + "Crypt <password>\r\n" + "Will Decrypt the password\r\n");
        }
 
 
    }
    public class CryptoHelper
    {
 
        // symmetric cryptographic algorithm provider
        private ICryptoTransform encryptor;     // encryptor object
        private ICryptoTransform decryptor;     // decryptor object
        private const int BufferSize = 1024;
 
        public CryptoHelper(string algorithmName, string key)
        {
            SymmetricAlgorithm provider = SymmetricAlgorithm.Create(algorithmName);
            provider.Key = Encoding.UTF8.GetBytes(key);
            provider.IV = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
 
            encryptor = provider.CreateEncryptor();
            decryptor = provider.CreateDecryptor();
        }
 
        public CryptoHelper(string key) : this("TripleDES", key) { }
 
        // default key 
        public CryptoHelper() : this("ABCDEFGHIJKLMNOP") { }
 
        // encrypt algorithm
        public string Encrypt(string clearText)
        {
            // create cleartext stream
            byte[] clearBuffer = Encoding.UTF8.GetBytes(clearText);
            MemoryStream clearStream = new MemoryStream(clearBuffer);
 
            // create empty ciphertext stream
            MemoryStream encryptedStream = new MemoryStream();
 
            CryptoStream cryptoStream =
                new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write);
 
            // write cleartext stream to buffer
            // wirte data in buffer into cryptoStream
            int bytesRead = 0;
            byte[] buffer = new byte[BufferSize];
            do
            {
                bytesRead = clearStream.Read(buffer, 0, BufferSize);
                cryptoStream.Write(buffer, 0, bytesRead);
            } while (bytesRead > 0);
 
            cryptoStream.FlushFinalBlock();
 
            // get length of encrypted text
            buffer = encryptedStream.ToArray();
            string encryptedText = Convert.ToBase64String(buffer);
            return encryptedText;
        }
 
        // decrypt algorithm
        public string Decrypt(string encryptedText)
        {
            byte[] encryptedBuffer = Convert.FromBase64String(encryptedText);
            Stream encryptedStream = new MemoryStream(encryptedBuffer);
 
            MemoryStream clearStream = new MemoryStream();
            CryptoStream cryptoStream =
                new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read);
 
            int bytesRead = 0;
            byte[] buffer = new byte[BufferSize];
 
            do
            {
                bytesRead = cryptoStream.Read(buffer, 0, BufferSize);
                clearStream.Write(buffer, 0, bytesRead);
            } while (bytesRead > 0);
 
            buffer = clearStream.GetBuffer();
            string clearText =
                Encoding.UTF8.GetString(buffer, 0, (int)clearStream.Length);
 
            return clearText;
        }
    }
}

C# 实现RunAs

类别: C# 发表评论

使用C#代码实现类似RunAs的功能:

Process proc = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
string pwd = "password";
string appPath = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Internet Explorer");
string appName = "iexplore.exe";
// 定义一个SecureString
System.Security.SecureString secureString = new System.Security.SecureString();
// 把password赋值给SecureString
foreach (char item in pwd.ToCharArray())
{
    secureString.AppendChar(item);
}
secureString.MakeReadOnly();
// 添加域,用户名和密码
psi.UserName = "estdvsvc";
psi.Domain = "redmond";
psi.Password = secureString;
// 设置工作目录和要启动的程序
psi.WorkingDirectory = appPath;
psi.FileName = System.IO.Path.Combine(appPath, appName);
// 设置启动的程序要打开的URL
psi.Arguments = "http://snippet.cn";
psi.UseShellExecute = false;
proc.StartInfo = psi;
proc.Start();

由于执行权限导致PowerShell Script无法启动

类别: PowerShell 发表评论

运行PowerShell脚本提示错误:

File C:\Users\xxx\Desktop\p.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see “get-help about_signing” for more details.
At line:1 char:8
+ .\p.ps1 <<<<
    + CategoryInfo          : NotSpecified: (:) [], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException

查了下原因,原来是PowerShell默认的执行权限的问题。在PowerShell中有4中执行权限:

  1. Restricted——默认的设置, 不允许任何script运行
  2. AllSigned——只能运行经过数字证书签名的script
  3. RemoteSigned——运行本地的script不需要数字签名,但是运行从网络上下载的script就必须要有数字签名
  4. Unrestricted——允许所有的script运行

可以使用Get-ExecutionPolicy来获取当前的权限,使用Set-ExecutionPolicy来更改执行权限

new features in each version of c#

类别: C# 发表评论

Each version of C# has a number of new features and generally a major theme. The major themes have been generics and nullable types in C# 2.0, LINQ in C# 3.0, and dynamic types in C# 4.0.

The major features added in each release are generally considered to be the following:

  1. C#1.0/.Net1.0/vs2002
  2. C#1.2/.Net1.1/vs2003
  3. C# 2.0/.Net2.0/vs2005
    • Generics (framework support was added, and C# benefited from this);
    • Iterator pattern (the yield keyword);
    • Anonymous methods (the delegate keyword),
    • Nullable types, and the null coalescing operator (??). 
  4. .Net3.0
  5. C# 3.0/.Net3.5/vs2008
    • Anonymous types,
    • Extension methods,
    • Object initializers, collection initializers,
    • Implicitly typed local variables (var keyword),
    • Lambda expressions (=>),
    • LINQ query expression pattern. 
  6. C# 4.0/.Net4.0/vs2010
    • Optional and Named Arguments
    • Dynamic typing (dynamic type)
    • Improved COM-Interop
    • Contra and Co-Variance.