Export Event Log (.evtx) without "run as administrator"

2.8k views Asked by At

Question: Is it possible to export an event log in a process not "run as administrator"?

I'm following the example code at https://msdn.microsoft.com/en-us/library/bb671203(v=vs.90).aspx

using (var els = new EventLogSession())
{
    els.ExportLogAndMessages("Security", PathType.LogName, "*", @"c:\temp\security.evtx");
}

This code runs successfully when I run the process using "run as administrator", but fails when not "run as administrator with the exception

System.UnauthorizedAccessException: "Attempted to perform an unauthorized operation."

Using similar code to access my application's event log

using (var els = new EventLogSession())
{
    els.ExportLogAndMessages("MyAppLog", PathType.LogName, "*", @"c:\temp\myapplog.evtx");
}

I get similar results except the exception is different:

System.Diagnostics.Eventing.Reader.EventLogException: "The directory name is invalid"

Am I doing something wrong, or is there a different approach that will allow me to get an event log exported to an .evtx file without requiring admin privileges?

Notes:

3

There are 3 answers

1
Martin Liversage On BEST ANSWER

Question: Is it possible to export an event log in a process not "run as administrator"?

Yes you can but only if you have the rights to access the event log you want to export.

However, your question seems to be more something like

Why can't I export my application's event log using EventLogSession? An EventLogException is thrown with the message "The directory name is invalid".

Looking into the source code for EventLogSession you can see that the call to ExportLogAndMessages will call the native function EvtExportLog. If this function fails the error code is retrieved by calling GetLastError. This native Windows error code is then mapped to one of several exceptions.

The exception that you experience is thrown if any of the following errors happen:

  • ERROR_FILE_NOT_FOUND (2): The system cannot find the file specified.
  • ERROR_PATH_NOT_FOUND (3): The system cannot find the path specified.
  • ERROR_EVT_CHANNEL_NOT_FOUND (15007): The specified channel could not be found. Check channel configuration.
  • ERROR_EVT_MESSAGE_NOT_FOUND (15027): The message resource is present but the message is not found in the string/message table.
  • ERROR_EVT_MESSAGE_ID_NOT_FOUND (15028): The message id for the desired message could not be found.
  • ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND (15002): The publisher metadata cannot be found in the resource.

If you specify a wrong event log name then ERROR_EVT_CHANNEL_NOT_FOUND is the error you encounter. My guess is that this is your problem.

However, you can call EvtExportLog yourself and inspect the native error code to better understand why the call fails:

[DllImport("kernel32.dll")]
static extern uint GetLastError();

[DllImport("wevtapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EvtExportLog(IntPtr session, string channelPath, string query, string targetFilePath, int flags);

var success = EvtExportLog(IntPtr.Zero, "MyAppLog", "*", @"c:\temp\myapplog.evtx", 1);
if (!success)
{
    var error = GetLastError();
    Console.WriteLine(error);
}

The native error code should give you a clear indication of what the underlying problem is.

5
Matt Smith On

Using the approach shown on pinvoke.net works without admin privileges for my custom application log (i.e. MyAppLog in the example above). This does not work for Security log example shown above (but I believe that is intended):

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern IntPtr OpenEventLog(string UNCServerName, string sourceName);

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool BackupEventLog(IntPtr hEventLog, string backupFile);

[DllImport("advapi32.dll", SetLastError = true)]
static extern bool CloseEventLog(IntPtr hEventLog);

void SaveLog(string eventLogName, string destinationDirectory)
{
    string exportedEventLogFileName = Path.Combine(destinationDirectory, eventLogName + ".evtx");

    IntPtr logHandle = OpenEventLog(Environment.MachineName, eventLogName);

    if (IntPtr.Zero != logHandle)
    {
       bool retValue = BackupEventLog(logHandle, exportedEventLogFileName);
       //If false, notify.
       CloseEventLog(logHandle);
    }
}
0
blearyeye On

This is kind of old, but I came back to it several times while trying to solve the same problem. I don't know any way to use EventLogSession without providing Admin credentials.

However, the Windows command wevtutil will let you export to an evtx file without Admin privileges. For example, running wevtutil epl Application Downloads\export-Application.evtx in a command window will export the Application event log.

To run from a C# program, you can use this method:

/// <summary>
/// Run wevtutil with the given parameters.
/// </summary>
/// <param name="programPath">Path to wevtutil</param>
/// <param name="programParameters">wevutil parameters</param>
/// <returns></returns>
/// <remarks>https://stackoverflow.com/a/37138255/468523</remarks>
private static (string info, string err) RunWevtUtil(string programPath, string programParameters)
{
    var process = new Process
    {
        StartInfo =
        {
            FileName = programPath,
            Arguments = programParameters,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        }
    };

    process.Start();
    var outputData = process.StandardOutput.ReadToEnd();
    var errorData = process.StandardError.ReadToEnd();
    process.WaitForExit();
    return (outputData, errorData);
}

For programPath, provide the complete path to wevtutil, typically @"C:\Windows\System32\wevtutil.exe". For programParameters you can use @"epl Application Downloads\export-Application.evtx". It returns a tuple of strings that give standard and error output.

You can use the Windows command line to test your parameters and then use those in the program.