C# exe提权

在C#项目中,设置属性->安全性->点击启用ClickOnce安全设置

bat 管理员身份运行python代码 bat 管理员权限运行_bat 管理员身份运行python代码

此时右边会显示app.manifest配置文件

bat 管理员身份运行python代码 bat 管理员权限运行_System_02

将asInvoler替换为requireAdministrator,程序启动时就会以管理员身份运行了

bat 管理员身份运行python代码 bat 管理员权限运行_安全_03

Bat批处理提权

给bat批处理提权,基本都是借助VBS脚本提权
@echo off
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' EQU '5' (
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
rem 后面跟想要执行的批处理

将这种方法的原理是:会先执行一个命令,该命令需要管理员权限,如果没有管理员权限就会返回错误码5,然后在系统的Temp文件创建一个VBS脚本,在VBS脚本里用ShellExecute方法以runas的方式开一个进程,runas开的进程会以管理员权限运行。开的那个进程会再执行这个批处理,此时因为有权限,会返回0,然后删除VBS文件,执行自己写的那部分脚本。

会出现的问题:如果需要从外界传参数给该bat批处理,需要在下面这个位置传,但是传过去的参数需要遵守VBS里的语法和ShellExecute的参数格式。如果出现了空格会十分麻烦。

echo UAC.ShellExecute "%~s0", "这里输入参数", "", "runas", 1 >> "%temp%\getadmin.vbs"
%1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close)&&[这里写想要执行的批处理]

这种方法和第一种相似,但mshta.exe程序比较敏感,慎用。

  1. 在C#里以runas的启动动作开一个进程执行批处理
private static System.Diagnostics.Process CreateShellExProcess(string cmd, string workingDir = "")
    {
    	//cmd为想要执行的进程名,workingDir为它的所在路径,如果在windows\system32可以为空
        var pStartInfo = new System.Diagnostics.ProcessStartInfo(cmd);
		pStartInfo.Verb = "runas";//设置该启动动作,会以管理员权限运行进程
        pStartInfo.Arguments = args;
        pStartInfo.CreateNoWindow = false;
        pStartInfo.UseShellExecute = true;
        pStartInfo.RedirectStandardError = false;
        pStartInfo.RedirectStandardInput = false;
        pStartInfo.RedirectStandardOutput = false;
        pStartInfo.Arguments = "这里传入参数";
        if (!string.IsNullOrEmpty(workingDir))
            pStartInfo.WorkingDirectory = workingDir;
        return System.Diagnostics.Process.Start(pStartInfo);
    }

该方法的实质其实和前两步一样。这种方法传入的参数如果带空格,会以空格分割参数,比如路径带的空格,这里如果用引号将路径括起来,会因为不符合VBS的语法而报错。

解决方法:将带空格的路径转换成dos短路径,就不会有空格的问题了

如C:\Program Files会被转换成C:\PROGRA~1

这里需要调用系统的API进行转换,在C++里可以直接调GetShortPathName方法,在C#里需要引用Dll

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern int GetShortPathName(
          [MarshalAs(UnmanagedType.LPTStr)]string path,
          [MarshalAs(UnmanagedType.LPTStr)]StringBuilder short_path,
          int short_len
          );
    public static string GetShortPath(string name)
    {
        int lenght = 0;
        lenght = GetShortPathName(name, null, 0);
        if (lenght == 0)
        {
            return name;
        }
        StringBuilder short_name = new StringBuilder(lenght);
        lenght = GetShortPathName(name, short_name, lenght);
        if (lenght == 0)
        {
            return name;
        }
        return short_name.ToString();
    }

GetShortPath会返回长路径的短路径。不过该路径必须在电脑中存在。

  • 上面这种提权方法,把批处理换成其他进程也有效