Feeds:
Записи
Комментарии

Archive for Июнь 2016

При просмотре событий журнала в Event Viewer, вкладка General содержит тело события в удобном для понимая виде и в зависимости от локализации ОС,по  возможности, отображает строки в заданной локализации.

 

evntvwr

В нашем примере событие  с номером 4663 содержит поле Accesses , которое имеет значение в удобном для нас виде — DELETE.

При переключении на вкладку Details и выбором формата XML, получаем значение формата %%N( N – число). Что является неудобным для понимания.

evtxml

В нашем примере AccessList имеет значение %%1537.

 

Теперь остается понять, откуда берется значение %%1537. Для этого обратимся к документации на портале Technet.

В разделе Log-name описан параметр ParameterMessageFile , который и указываем где хранятся описание.

HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Log-name\Source-name

 

 

Data type

Range

Default value

REG_EXPAND_SZ

Path and file name [; Path and file name]

(None)

 

Description

Stores the location of the file that contains values for variables in the event description. This file is optional.

The descriptive text in the event message file can contain variables. The variables indicated by %n are resolved by substituting data from the event record. The variables indicated by %%n are resolved by substituting text from a parameter message file (stored in the ParameterMessageFile entry). The Event Log service locates the correct values and replaces the variables before displaying the text in the Description field in Event Viewer.

 

reg

 

Получим значения ключа реестра ParameterMessageFile :

$key = "HKLM:\SYSTEM\CurrentControlSet\Services\EventLog"            
$property = "ParameterMessageFile"            
$hp = @{n="Path";e={            
 $_.PsPath.Substring($_.PsPath.IndexOf("EventLog\") + 9)}            
},$property            
Get-ChildItem -Path $key -Recurse |             
 Get-ItemProperty -Name $property -ErrorAction SilentlyContinue |             
  Select-Object -Property $hp

 

Примерный вывод:

messagefile

 

С помощью редактора ресурсов, например Resource Hacker, посмотрим, что содержит C:\Windows\System32\MsObjs.dll ( System\DS используется для события 4663).

 

rh

 

0x601, «DELETE\r\n» (где HEX –> DEC 0x601 –> 1537)

Выгрузим значения из MESSAGETABLE.  Спасибо  Hans Passant за пример кода  Marshaling a message table resource.

 

param(            
    # Путь к библиотеки из ключа ParameterMessageFile            
 $DLLPath = (Join-Path -Path $env:SystemRoot -ChildPath \System32\msobjs.dll)            
)            
            
            
# Определяем сигнатуры            
#            
# 1. LoadLibrary             
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175.aspx            
# 2. https://msdn.microsoft.com/en-us/library/windows/desktop/ms683152.aspx            
#            
# Процессы вызывают функцию LoadLibrary  для явного связывания             
# с библиотекой DLL.При успешном завершении функция сопоставляет указанную библиотеку DLL            
# с адресным пространством вызывающего процесса и возвращает дескриптор библиотеки DLL            
#            
# Если у библиотеки DLL есть функция точки входа, операционная система вызывает эту            
# функцию в контексте потока, в котором вызвана функция LoadLibrary.Функция точки входа             
# не вызывается, если библиотека DLL уже присоединена к процессу в результате             
# предыдущего вызова функции LoadLibrary, за которым не последовал вызов функции FreeLibrary.            
#            
# 3. FindResource            
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms648042.aspx            
#            
# Функция FindResource выясняет место ресурса с заданным типом и именем в указанном модуле.             
#            
#            
# 4. LockResource            
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms648047.aspx            
#            
# Функция LockResource блокирует указанный ресурс в памяти.            
#            
# 5. LoadResource            
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms648046.aspx            
#             
# Функция читает ресурс из модуля.            
#            
$signature = @"
namespace Win32 {
	using System;
	using System.Runtime.InteropServices;
	
	[StructLayout(LayoutKind.Sequential)]
	public struct MESSAGE_RESOURCE_BLOCK {
		public int LowId;
		public int HighId;
		public int OffsetToEntries;
	}
	
	public class API {
		[DllImport("kernel32.dll", SetLastError = true)]
			public static extern IntPtr LoadLibrary(string fileName);
		[DllImport("kernel32.dll", SetLastError = true)]
			public static extern IntPtr FindResource(IntPtr hModule, int lpID, int lpType);
		[DllImport("kernel32.dll")]
			public static extern IntPtr LockResource(IntPtr hResData);
		[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
			public static extern IntPtr LoadResource(IntPtr hModule,IntPtr hResInfo);
		[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
			public static extern bool FreeLibrary(IntPtr hModule);
	}
}
"@            
            
# Загружаем сигнатуры             
Add-Type $signature            
            
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms648009.aspx            
# RT_MESSAGETABLE MAKEINTRESOURCE(11) - Message-table entry.            
$RT_MESSAGETABLE = 11            
$msg = New-Object -TypeName 'System.Collections.Generic.Dictionary[int,string]'            
            
# Получаем указатель на библиотеку            
$hModule = [Win32.API]::LoadLibrary($DLLPath)            
# Получаем расположения ресурса            
$hTable = [Win32.API]::FindResource($hModule, 1, $RT_MESSAGETABLE)            
            
if($hTable) {            
    # Указатель на ресурс            
 $rTable = [Win32.API]::LoadResource($hModule, $hTable)            
 $mTable = [Win32.API]::LockResource($rTable)            
             
    # Количество полей в ресурсе            
 $numberOfBlocks = [System.Runtime.InteropServices.Marshal]::ReadInt32($mTable)            
 $blockPtr = [IntPtr]::Add($mTable, 4)            
    # Определяем размер структуры Win32.MESSAGE_RESOURCE_BLOCK            
 $strMRB = New-Object -TypeName Win32.MESSAGE_RESOURCE_BLOCK            
 $blockSize = [System.Runtime.InteropServices.Marshal]::SizeOf($strMRB)            
             
    # Получаем значения полей из ресурса            
 for($i=0 ; $i -lt $numberOfBlocks ; $i++) {            
  $block = [System.Runtime.InteropServices.Marshal]::PtrToStructure($blockPtr,
[System.Type][Win32.MESSAGE_RESOURCE_BLOCK])            
  $entryPtr = [IntPtr]::Add($mTable, $block.OffsetToEntries)            
            
        for ($id = $block.LowId; $id -le $block.HighId; $id++) {            
            $length = [System.Runtime.InteropServices.Marshal]::ReadInt16($entryPtr)            
            $flags = [System.Runtime.InteropServices.Marshal]::ReadInt16($entryPtr, 2)            
            $textPtr = [IntPtr]::Add($entryPtr, 4)            
            $text = "Bad flags??";            
            if ($flags -eq 0) {            
                $text = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($textPtr)            
            }            
            elseif ($flags -eq 1) {            
                $text = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($textPtr)            
            }            
            $text = $text.Replace("`r`n", "").Trim()            
   $msg.Add($id,$text)            
            
            $entryPtr = [IntPtr]::Add($entryPtr, $length)            
        }            
        $blockPtr = [IntPtr]::Add($blockPtr, $blockSize)            
 }            
}            
            
# Освобождаем ресурсы            
[Win32.API]::FreeLibrary($hModule) | Out-Null

 

При вызове метода [Runtime.InteropServices.Marshal]::PtrToStructure с установленным Microsoft .NET Framework 4.5.1 или the Microsoft .NET Framework 4.5.2 получаем исключение:

The specified structure must be blittable or have layout information.

В статье указан вариант решения, надо явно привести к типу System.Type

Exceptions in Windows PowerShell, other dynamic languages, and dynamically executed C# code when code that targets the .NET Framework calls some methods

$size = [System.Runtime.InteropServices.Marshal]::SizeOf([System.Type] $type)$obj = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ptr, [System.Type] $type)

 

Пример выполнения:

 

image

 

Касаемо события 4663, можно легко обойтись без получение данных из ресурса. Поле Message содержит уже преобразованное значение, Access Mask легко привести к типу Security.AccessControl.FileSystemRights.

evtposh

PS >

$evt.Message.Split(«`n») -match «Access(es|\sMask)» -replace «:\s+»,»=» |

Out-String | ConvertFrom-StringData

Name                           Value

—-                           ——

Access Mask                    0x4

Accesses                       AppendData (or AddSubdirectory or CreatePipeInstance)

PS >

[System.Security.AccessControl.FileSystemRights]$evt.Properties[9].Value

AppendData

 

В первом скрипте выгружали все значения ресурса. С помощью функции  FormatMessage можно получить  значения по коду.

Function Get-FormatMessage {            
 [OutputType('System.String')]            
 [CmdletBinding()]            
  param(            
   [Parameter(Mandatory = $true)]            
   [int]$MessageCode,            
   [string]$DllPath = (Join-Path -Path $env:SystemRoot -ChildPath \System32\msobjs.dll)            
  )            
            
$signature = @"
	namespace Win32 {
		using System;
		using System.Runtime.InteropServices;
		
		
		public class API {
		
			[DllImport("kernel32.dll", SetLastError=true)]
				public static extern uint FormatMessage(
					uint dwFlags,
					IntPtr lpSource,
					int dwMessageId,
					uint dwLanguageId,
					ref IntPtr lpBuffer,
					uint nSize,
					IntPtr Arguments
				);
			[DllImport("kernel32.dll", SetLastError = true)]
				public static extern IntPtr LoadLibrary(string fileName);
			[DllImport("kernel32.dll", SetLastError = true)]
				public static extern IntPtr LoadResource(IntPtr hModule,IntPtr hResInfo);
			[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
				public static extern bool FreeLibrary(IntPtr hModule);
			[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
				public static extern IntPtr LocalFree(IntPtr hMem);
		}
	}
"@            
             
 try {Add-Type $signature}            
    catch {Write-Warning $_.Exception.Message; return}            
            
 $FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100            
 $FORMAT_MESSAGE_FROM_HMODULE  = 0x00000800            
 $FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200            
            
 $hModule = [Win32.API]::LoadLibrary($DllPath)            
             
 if($hModule) {            
  $dwFlags = $FORMAT_MESSAGE_ALLOCATE_BUFFER -bor $FORMAT_MESSAGE_FROM_HMODULE -bor $FORMAT_MESSAGE_IGNORE_INSERTS            
  $lpBuffer = [IntPtr]::Zero            
            
  if ([Win32.API]::FormatMessage($dwFlags,$hModule,$MessageCode,0,[ref]$lpBuffer,0,[IntPtr]::Zero)) {            
   [Runtime.InteropServices.Marshal]::PtrToStringAnsi($lpBuffer).Trim()            
  }            
  else {            
    Write-Output "No messages are assoicated with code : $MessageCode ."            
  }            
 }            
            
 [Win32.API]::FreeLibrary($hModule) | Out-Null            
 [Win32.API]::LocalFree($lpBuffer) | Out-Null            
}

Пример выполнения:

PS > Get-FormatMessage -MessageCode 1537

DELETE

PS > Get-FormatMessage -MessageCode 1539

WRITE_DAC

PS > Get-FormatMessage -MessageCode 4418

AppendData (or AddSubdirectory or CreatePipeInstance)

Реклама

Read Full Post »