/*
文件名: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)
没有评论:
发表评论