Принудительно запустить программу без прав администратора? - PullRequest
1 голос
/ 19 марта 2012

У меня есть программа .net, которая запрашивает права администратора по умолчанию всякий раз, когда я пытаюсь ее запустить.Я не знаю ни одной причины, по которой он НУЖДАЕТСЯ в этих привилегиях в моем конкретном случае, поэтому я просто подозреваю, что за ним стоит ленивое программирование (принудительно осуществляя доступ администратора на тот случай, если это может понадобиться).

Есть ли способ, которым яможет заставить его не пытаться поднять и запустить с обычными правами доступа?Например, изменив встроенный манифест или каким-либо программным способом?

Запуск обычного приложения с правами администратора довольно тривиально, но возможно ли обратное?

Обновление: Iиметь доступ только к скомпилированному .exe, но не к исходному коду или оригинальному файлу манифеста.Я посмотрел на встроенный манифест .exe через ManifestView Кенни Керра, и он определенно запрашивает привилегии администратора, поскольку он включает следующее:

<requestedPrivileges>
    <requestedExecutionLevel level="requireAdministrator" />
</requestedPrivileges>

Есть ли способизменить манифест скомпилированной сборки .exe?Например, есть ли какой-нибудь инструмент для этого или информация о том, как это сделать программно?

Ответы [ 2 ]

1 голос
/ 20 марта 2012

Я попытался создать небольшое приложение на C #, чтобы изменить встроенный манифест, чтобы он не запрашивал привилегии администратора. Это решение, которое я наконец-то придумал, сделало несколько вызовов Win32 для извлечения манифеста и замены существующего манифеста. Это уже достаточно долго, поэтому я пропустил часть, где я фактически изменяю манифест (только некоторые основные операции с XML).

Здесь есть два статических метода: LoadManifestResource , который загружает строковое представление встроенного манифеста исполняемого файла, и SaveManifestResource , который сохраняет строковое представление ресурса манифеста в указанный исполняемый файл, перезаписывая старый.

Это быстрое и грязное решение, которое отлично сработало для меня, но вполне может работать не во всех случаях.

public static class Library
{
    [DllImport("kernel32.dll")]
    static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool FreeLibrary(IntPtr hModule);

    [DllImport("kernel32.dll")]
    static extern IntPtr FindResource(IntPtr hModule, int lpName, int lpType);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);

    [DllImport("kernel32.dll")]
    static extern IntPtr LockResource(IntPtr hResData);

    [DllImport("Kernel32.dll", EntryPoint = "SizeofResource", SetLastError = true)]
    private static extern uint SizeofResource(IntPtr hModule, IntPtr hResource);

    [System.Flags]
    enum LoadLibraryFlags : uint
    {
        DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
        LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
        LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
        LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
        LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
        LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008
    }

    public static unsafe string LoadManifestResource(string fileName)
    {
        // load library to retrieve manifest from
        var libraryHandle = LoadLibraryEx(fileName, IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_AS_DATAFILE);
        if (libraryHandle.ToInt32() == 0)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), "couldn't load library");
        }
        try
        {
            // find manifest
            var resource = FindResource(libraryHandle, 1, 24);
            if (resource.ToInt32() == 0)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "couldn't find manifest resource");
            }

            // load manifest
            var loadedManifest = LoadResource(libraryHandle, resource);
            if (loadedManifest.ToInt32() == 0)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "couldn't load manifest resource");
            }

            // lock manifest
            var lockedManifest = LockResource(loadedManifest);
            if (lockedManifest.ToInt32() == 0)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "couldn't lock manifest resource");
            }

            // calculate size of manifest, copy to byte array and convert to string
            int manifestSize = (int)SizeofResource(libraryHandle, resource);

            byte[] data = new byte[manifestSize];
            Marshal.Copy(lockedManifest, data, 0, manifestSize);
            var manifest = Encoding.UTF8.GetString(data);

            return manifest;
        }
        finally
        {
            FreeLibrary(libraryHandle);
        }
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr BeginUpdateResource(string pFileName,
       [MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool UpdateResource(IntPtr hUpdate, int lpType, int lpName, ushort wLanguage, IntPtr lpData, uint cbData);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);

    public static unsafe void SaveManifestResource(string file, string manifest)
    {
        var hUpdate = BeginUpdateResource(file, false);

        byte[] bytes = Encoding.UTF8.GetBytes(manifest);
        IntPtr ptr = Marshal.AllocHGlobal(bytes.Length);
        try
        {
            Marshal.Copy(bytes, 0, ptr, bytes.Length);

            if (!UpdateResource(hUpdate, 24, 1, 0, ptr, (uint)bytes.Length))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            if (!EndUpdateResource(hUpdate, false))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }
        finally
        {
            Marshal.FreeHGlobal(ptr);
        }
    }
}
0 голосов
/ 19 марта 2012

Если у вас есть код в приложении, требующий прав администратора, я думаю, вы не сможете запустить приложение.

Некоторые коды / apis помечены, чтобы требовать определенных привилегий.Поэтому я не верю, что вы можете пройти мимо: /

Единственное решение, которое я вижу, это разделение инкриминированного кода на модуль, который вы можете загружать или не загружать.Так что это позволит вам запускать обе версии, сохраняя «тот же» продукт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...