EternalWindows
LSA / サブカテゴリの設定

前節では、各カテゴリが定義するサブカテゴリを列挙しました。 今回は、カテゴリとサブカテゴリの関係をより深く見ていくことにします。 まず、カテゴリの設定をLsaSetInformationPolicyで行った場合、 その設定はサブカテゴリに反映されることになります。 たとえば、オブジェクトアクセスのカテゴリにはファイルシステムなどのサブカテゴリがありますが、 オブジェクトアクセスに成功の監査を設定した場合は、 ファイルシステムなどのサブカテゴリにも成功の監査が設定されることになります。 つまり、全てのサブカテゴリに同じ設定を行いたい場合は、 LsaSetInformationPolicyを呼び出すことになります。

それでは、任意のサブカテゴリを設定するにはどうすればよいのでしょうか。 これには、AuditSetSystemPolicyを呼び出すことになります。 カテゴリが監査しないと設定されていたとしても、 サブカテゴリに設定された情報は考慮される点に注意してください。

BOOLEAN WINAPI AuditSetSystemPolicy(
  PCAUDIT_POLICY_INFORMATION pAuditPolicy,
  ULONG PolicyCount
);

pAuditPolicyは、設定したいサブカテゴリの情報を格納したAUDIT_POLICY_INFORMATION構造体のアドレスを指定します。 PolicyCountは、pAuditPolicyの要素数を指定します。

今回のプログラムは、ログオンのカテゴリを監査しないように設定した後、 サブカテゴリのログオンに成功の監査を設定しています。 ログオンのカテゴリには、ログオフなどのサブカテゴリがありますが、 これらは監査されないことになります。

#define INITGUID
#include <windows.h>
#include <ntsecapi.h>

BOOL SetAuditPolicy(POLICY_AUDIT_EVENT_TYPE eventType, DWORD dwEventOption);
BOOL EnablePrivilege(LPTSTR lpszPrivilege, BOOL bEnable);

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	AUDIT_POLICY_INFORMATION auditPolicy;

	if (!EnablePrivilege(SE_SECURITY_NAME, TRUE)) {
		MessageBox(NULL, TEXT("SE_SECURITY_NAME特権の有効に失敗しました。"), NULL, MB_ICONWARNING);
		return 0;
	}

	if (!SetAuditPolicy(AuditCategoryLogon, POLICY_AUDIT_EVENT_UNCHANGED | POLICY_AUDIT_EVENT_NONE)) {
		MessageBox(NULL, TEXT("カテゴリのポリシーの設定に失敗しました。"), NULL, MB_ICONWARNING);
		return 0;
	}

	auditPolicy.AuditSubCategoryGuid = Audit_Logon_Logon;
	auditPolicy.AuditingInformation = POLICY_AUDIT_EVENT_SUCCESS | POLICY_AUDIT_EVENT_NONE;

	if (AuditSetSystemPolicy(&auditPolicy, 1))
		MessageBox(NULL, TEXT("サブカテゴリのポリシーを設定しました。"), TEXT("OK"), MB_OK);
	else
		MessageBox(NULL, TEXT("サブカテゴリのポリシーの設定に失敗しました。"), NULL, MB_ICONWARNING);

	return 0;
}

BOOL SetAuditPolicy(POLICY_AUDIT_EVENT_TYPE eventType, DWORD dwEventOption)
{
	NTSTATUS                  ns;
	LSA_HANDLE                hPolicy;
	LSA_OBJECT_ATTRIBUTES     objectAttributes;
	PPOLICY_AUDIT_EVENTS_INFO pAuditInfo;

	ZeroMemory(&objectAttributes, sizeof(LSA_OBJECT_ATTRIBUTES));
	objectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);

	ns = LsaOpenPolicy(NULL, &objectAttributes, POLICY_VIEW_AUDIT_INFORMATION | POLICY_SET_AUDIT_REQUIREMENTS, &hPolicy);
	if (LsaNtStatusToWinError(ns) != ERROR_SUCCESS)
		return FALSE;

	LsaQueryInformationPolicy(hPolicy, PolicyAuditEventsInformation, (LPVOID *)&pAuditInfo);

	pAuditInfo->EventAuditingOptions[eventType] = dwEventOption;
	LsaSetInformationPolicy(hPolicy, PolicyAuditEventsInformation, (LPVOID)pAuditInfo);

	LsaFreeMemory(pAuditInfo);
	LsaClose(hPolicy);

	return TRUE;
}

BOOL EnablePrivilege(LPTSTR lpszPrivilege, BOOL bEnable)
{
	BOOL             bResult;
	LUID             luid;
	HANDLE           hToken;
	TOKEN_PRIVILEGES tokenPrivileges;

	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
		return FALSE;
	
	if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid)) {
		CloseHandle(hToken);
		return FALSE;
	}

	tokenPrivileges.PrivilegeCount           = 1;
	tokenPrivileges.Privileges[0].Luid       = luid;
	tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
	
	bResult = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
	
	CloseHandle(hToken);

	return bResult && GetLastError() == ERROR_SUCCESS;
}

まず、自作関数のEnablePrivilegeでSE_SECURITY_NAME特権を有効にします。 これは、AuditSetSystemPolicyの呼び出しに必要です。 自作関数のSetAuditPolicyには、ログオンのカテゴリを示すAuditCategoryLogonと、 それを監査しないことを示すPOLICY_AUDIT_EVENT_UNCHANGEDを指定します。 また、設定の場合はPOLICY_AUDIT_EVENT_NONEも必要です。 SetAuditPolicyが成功した後は、AuditSetSystemPolicyでサブカテゴリのログオンに成功の監査を指定します。 これにより、ログオンだけを監査できるようになります。 ログオンのサブカテゴリは、Audit_Logon_LogonというGUIDで表すことができますが、 そのためにはINITGUIDを定義しておくことになります。

ユーザー毎の設定

サブカテゴリの設定は、ユーザー毎に行うこともできます。 この機能の優れているところは、LsaSetInformationPolicyによってカテゴリが変更されても、 ユーザー毎に設定されたサブカテゴリには影響がないという点です。 ユーザー毎にサブカテゴリを設定するには、AuditSetPerUserPolicyを呼び出します。

HANDLE                   hToken;
PTOKEN_USER              pTokenUser;
DWORD                    dwLength;
AUDIT_POLICY_INFORMATION auditPolicy;

OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength);
pTokenUser = (PTOKEN_USER)LocalAlloc(LPTR, dwLength);
GetTokenInformation(hToken, TokenUser, pTokenUser, dwLength, &dwLength);

auditPolicy.AuditSubCategoryGuid = Audit_Logon_Logon;
auditPolicy.AuditingInformation = PER_USER_AUDIT_SUCCESS_INCLUDE | PER_USER_AUDIT_NONE;

AuditSetPerUserPolicy(pTokenUser->User.Sid, &auditPolicy, 1);

AuditSetPerUserPolicyは第1引数にユーザーのSIDを要求するため、 現在のプロセスに割り当てられたトークンのトークンユーザーを指定します。 つまり、現在のユーザーに対してサブカテゴリが設定されるようになります。 サブカテゴリが設定されたユーザーは、AuditEnumeratePerUserPolicyで列挙できるようになります。



戻る