/* 文件名:GetSecurityUserInfo.C 功能:获取当前操作注册表的进程的用户. SOURCE文件内容如下: TARGETNAME=test TARGETTYPE=DRIVER TARGETLIBS=$(DDK_LIB_PATH)\ksecdd.lib SOURCES=GetSecurityUserInfo.C TARGETPATH=obj made by correy made at 2013.11.15 email:kouleguan at hotmail dot com homepage:http://correy.webs.com 不足之处,敬请指出. */ #include <ntifs.h> LARGE_INTEGER Cookie; NTSTATUS print_current_user() /* 打印当前操作的当前进程的用户名等. */ { NTSTATUS status = 0; PACCESS_TOKEN pat = 0; UNICODE_STRING SidString = {0}; PTOKEN_STATISTICS pts; PSecurityUserData PUserInformation; pat = PsReferencePrimaryToken(PsGetCurrentProcess()); status = SeQueryInformationToken(pat, TokenStatistics,(PVOID *) & pts); if( !NT_SUCCESS( status ) ) { PsDereferencePrimaryToken(pat); return status; } //还有一种情况也会发生如下情况,就是在Windows server 2008 X64上,具体的有待检查和添加. if (pts->AuthenticationId.HighPart == 0 && pts->AuthenticationId.LowPart == 999)//为何是这两个数,不得而知. { //获取到了系统帐户,就是system,本地系统帐户. //打印的消息一般如下: //UserName :KOUDAQIANG-2008$ //LogonServer : //LogonDomainName :WORKGROUP //SID :S-1-5-18 KdPrint(("UserName:system\n")); PsDereferencePrimaryToken(pat); return status; } //可以考虑把下面的代码写成工作线程. //下面的函数需要连接Ksecdd.lib,如:TARGETLIBS=$(DDK_LIB_PATH)\ksecdd.lib status = GetSecurityUserInfo(&pts->AuthenticationId, 0, &PUserInformation); if( !NT_SUCCESS( status ) ) { return status; } //status = RtlConvertSidToUnicodeString(&SidString, PUserInformation->pSid,TRUE); //if( !NT_SUCCESS( status ) )//成功.#define STATUS_INVALID_SID ((NTSTATUS)0xC0000078L) -1073741704 //{ // return status; //} KdPrint(("UserName:%wZ\n",&PUserInformation->UserName)); //KdPrint(("LogonServer :%wZ\n",&PUserInformation->LogonServer)); //KdPrint(("LogonDomainName :%wZ\n",&PUserInformation->LogonDomainName)); //KdPrint(("SID :%wZ\n",&SidString)); //RtlFreeUnicodeString(&SidString); LsaFreeReturnBuffer(PUserInformation); PsDereferencePrimaryToken(pat); return status; } EX_CALLBACK_FUNCTION RegistryCallback; NTSTATUS RegistryCallback(__in PVOID CallbackContext, __in_opt PVOID Argument1, __in_opt PVOID Argument2) { print_current_user(); return STATUS_SUCCESS; } DRIVER_UNLOAD Unload; VOID Unload(__in PDRIVER_OBJECT DriverObject) { CmUnRegisterCallback(Cookie); } #pragma INITCODE DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath) { KdBreakPoint(); DriverObject->DriverUnload = Unload; return CmRegisterCallback(RegistryCallback, NULL, &Cookie); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* 文件名:RtlFormatCurrentUserKeyPath.C 功能:获取当前操作注册表的进程的用户的SID. made by correy made at 2014.06.14 homepage:http://correy.webs.com 不足之处,敬请指出. */ #include <ntifs.h> #include <windef.h> //#pragma comment (lib,"ksecdd.lib") LARGE_INTEGER Cookie; //http://msdn.microsoft.com/en-us/library/ff899322(v=vs.85).aspx //Initializes the supplied buffer with a string representation of the SID for the current user. //extern NTSTATUS /*WINAPI*/ RtlFormatCurrentUserKeyPath(/*_Out_*/ UNICODE_STRING CurrentUserKeyPath); //此函数在XP就已经导出,但直接引用会出现链接错误。 typedef NTSTATUS (WINAPI * RtlFormatCurrentUserKeyPath)(/*_Out_*/ UNICODE_STRING * CurrentUserKeyPath); //那咱就动态获取吧! //CurrentUserKeyPath [out] //String that represents the current user's root key in the Registry. Caller must call RtlFreeUnicodeString to free the buffer when done with it. /* 注意:微软的官方的链接里面是错误的。 开始我还以为这是我第一个发现参数传递结构,而不是指针的。 */ RtlFormatCurrentUserKeyPath g_p_RtlFormatCurrentUserKeyPath; PVOID ExpAllocateStringRoutine (IN SIZE_T NumberOfBytes) { return ExAllocatePoolWithTag (PagedPool,NumberOfBytes,'grtS'); } //上下的定义摘自:\wrk\WindowsResearchKernel-WRK\WRK-v1.2\base\ntos\ex\pool.c #ifdef ALLOC_DATA_PRAGMA #pragma const_seg("PAGECONST") #endif const PRTL_ALLOCATE_STRING_ROUTINE RtlAllocateStringRoutine = ExpAllocateStringRoutine; const PRTL_FREE_STRING_ROUTINE RtlFreeStringRoutine = (PRTL_FREE_STRING_ROUTINE)ExFreePool; #ifdef ALLOC_DATA_PRAGMA #pragma const_seg() #endif // Maximum size of TOKEN_USER information. #define SIZE_OF_TOKEN_INFORMATION \ sizeof( TOKEN_USER ) \ + sizeof( SID ) \ + sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES //这个函数及上面的定义摘自WRK-v1.2/base/ntos/rtl/regutil.c,但是有修改,可以在驱动中使用或者利用。 NTSTATUS RtlFormatCurrentUserKeyPath0(OUT PUNICODE_STRING CurrentUserKeyPath) /*++ Routine Description: Initialize the supplied buffer with a string representation of the current user's SID. 这个函数还是有必要说明几点: 1.要获取当前用户的SID,首先的不是判断SID而是当前用户,再获取SID这很容易。 一台计算机同时登陆几个不同的用户是正常的。 通常一个普通的用户一个会话,包括远程登录的。 所以另一个捷径是判断会话,这有公开/导出的函数。如某个进程或者线程属于哪个会话。 2.此函数有发掘利用的价值,看你怎么用了。 3.此函数获取的不是当前登录用户的SID,而是当前的操作的进程的用户的SID,如系统帐户,网络帐户,服务帐户等。 Arguments: CurrentUserKeyPath - Returns a string that represents the current user's root key in the Registry. Caller must call RtlFreeUnicodeString to free the buffer when done with it. Return Value: NTSTATUS - Returns STATUS_SUCCESS if the user string was succesfully initialized. --*/ { HANDLE TokenHandle = 0; UCHAR TokenInformation[ SIZE_OF_TOKEN_INFORMATION ]; ULONG ReturnLength; ULONG SidStringLength = 0 ;//添加初始化为0. UNICODE_STRING SidString ; NTSTATUS Status; // Inside the kernel we can tell rapidly if we are impersonating. Status = STATUS_NO_TOKEN; if (PsIsThreadTerminating (PsGetCurrentThread ())) {//原来是PS_IS_THREAD_IMPERSONATING。 Status = ZwOpenThreadTokenEx (NtCurrentThread(), TOKEN_READ, TRUE, OBJ_KERNEL_HANDLE, &TokenHandle); if ( !NT_SUCCESS( Status ) && ( Status != STATUS_NO_TOKEN ) ) { return Status; } } if ( !NT_SUCCESS( Status ) ) { Status = ZwOpenProcessTokenEx (NtCurrentProcess(), TOKEN_READ, OBJ_KERNEL_HANDLE, &TokenHandle); if ( !NT_SUCCESS( Status )) { return Status; } } Status = ZwQueryInformationToken( TokenHandle, TokenUser, TokenInformation, sizeof( TokenInformation ), &ReturnLength); ZwClose( TokenHandle ); if ( !NT_SUCCESS( Status )) { return Status; } //Status = RtlLengthSidAsUnicodeString(((PTOKEN_USER)TokenInformation)->User.Sid, &SidStringLength); //if ( !NT_SUCCESS( Status ) ) { // return Status ; //} //因为RtlLengthSidAsUnicodeString在XP上没有导出,所以用下面的两个函数替换。 if (!RtlValidSid(((PTOKEN_USER)TokenInformation)->User.Sid)) { return Status ; } SidStringLength = RtlLengthSid(((PTOKEN_USER)TokenInformation)->User.Sid); if (!SidStringLength) { return Status ; } CurrentUserKeyPath->Length = 0; CurrentUserKeyPath->MaximumLength = (USHORT)(SidStringLength + sizeof( L"\\REGISTRY\\USER\\" ) + sizeof( UNICODE_NULL )); CurrentUserKeyPath->Buffer = (RtlAllocateStringRoutine)( CurrentUserKeyPath->MaximumLength ); if (CurrentUserKeyPath->Buffer == NULL) { return STATUS_NO_MEMORY; } RtlAppendUnicodeToString( CurrentUserKeyPath, L"\\REGISTRY\\USER\\" );// Copy "\REGISTRY\USER" to the current user string. SidString.MaximumLength = CurrentUserKeyPath->MaximumLength;//(USHORT)SidStringLength ;这里有修改 原数乘以2应该也可以的,不然RtlConvertSidToUnicodeString失败。 SidString.Length = 0 ; SidString.Buffer = CurrentUserKeyPath->Buffer + (CurrentUserKeyPath->Length / sizeof(WCHAR) ); Status = RtlConvertSidToUnicodeString( &SidString, ((PTOKEN_USER)TokenInformation)->User.Sid, FALSE); if ( !NT_SUCCESS( Status )) {//#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L) RtlFreeUnicodeString( CurrentUserKeyPath ); } else { CurrentUserKeyPath->Length += SidString.Length ; } return Status; } NTSTATUS print_current_user() /* 打印当前操作的当前进程的用户名等. */ { NTSTATUS status = 0; UNICODE_STRING CurrentUserKeyPath = {0}; status = g_p_RtlFormatCurrentUserKeyPath(&CurrentUserKeyPath); if( !NT_SUCCESS( status ) ) { return status; } KdPrint(("CurrentUserKeyPath:%wZ\n",&CurrentUserKeyPath));//"\REGISTRY\USER\S-1-5-18" RtlFreeUnicodeString(&CurrentUserKeyPath); status = RtlFormatCurrentUserKeyPath0(&CurrentUserKeyPath); if( !NT_SUCCESS( status ) ) { return status; } KdPrint(("CurrentUserKeyPath:%wZ\n",&CurrentUserKeyPath));//"\REGISTRY\USER\S-1-5-18" RtlFreeUnicodeString(&CurrentUserKeyPath); return status; } EX_CALLBACK_FUNCTION RegistryCallback; NTSTATUS RegistryCallback(__in PVOID CallbackContext, __in_opt PVOID Argument1, __in_opt PVOID Argument2) { print_current_user(); return STATUS_SUCCESS; } DRIVER_UNLOAD Unload; VOID Unload(__in PDRIVER_OBJECT DriverObject) { CmUnRegisterCallback(Cookie); } #pragma INITCODE DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath) { UNICODE_STRING us_RtlFormatCurrentUserKeyPath; KdBreakPoint(); DriverObject->DriverUnload = Unload; RtlInitUnicodeString( &us_RtlFormatCurrentUserKeyPath, L"RtlFormatCurrentUserKeyPath" ); g_p_RtlFormatCurrentUserKeyPath = MmGetSystemRoutineAddress(&us_RtlFormatCurrentUserKeyPath); if (g_p_RtlFormatCurrentUserKeyPath == NULL) { return STATUS_UNSUCCESSFUL; } return CmRegisterCallback(RegistryCallback, NULL, &Cookie); }
2013年11月15日星期五
在驱动中获取进程的用户名及SID
订阅:
博文评论 (Atom)
没有评论:
发表评论