阅读:6033回复:37
内核中如何得到当前进程的句柄?
要得到当时前进程和线程的句柄,如何做?
|
|
|
沙发#
发布于:2002-06-22 13:53
http://www.chinawolf.com/~lu0/sys/20010616.html
至于其他方法,可以试试在EPROCESS/ETHREAD中得到ID,再ZwOpen***** |
|
板凳#
发布于:2002-06-22 14:46
呵呵!句柄是系统用来区分不同的内核对象的!看看核心编程就知道了
|
|
地板#
发布于:2002-06-22 15:54
from Irp to get ProcessHandle/ThreadHandle
first get ETHREAD data structure. if work in original context, pEthread =PsGetCurrentThread() is ok. if not, pEthread = Irp->Tail.Overlay.Thread; for 2k. use pEthread->ThreadsProcess to get PEPROCESS then dwProcessId = pProcess->UniqueProcessId; for XP. EPROCESs and ETHREAD change alot, _asm { mov eax,pEthread add eax, 0x1EC mov pClientID ,eax } pClientID hold ProcessID and ThreadID. then just like pjf said, you need ZwOpenProcess or ZwOpenThread to get process/thread handle. take care that psgetcurrentprocessid DOES not return a valid process ID. |
|
地下室#
发布于:2002-06-22 18:19
现在只有ZwOpen...这一条路较方便了。
以前直接在句柄表里加过东西,但此法跟系统版本相关了。 |
|
5楼#
发布于:2002-06-23 13:36
from Irp to get ProcessHandle/ThreadHandle 老兄:你这里得到的并晃是句柄,而是指针。 DDK文档中如下描述: PEPROCESS PsGetCurrentProcess( ); PsGetCurrentProcess returns a pointer to the process of the current thread. |
|
|
6楼#
发布于:2002-06-23 14:43
老兄:你这里得到的并晃是句柄,而是指针。
--------------------------------------------------------------------- zdhe的意思与我一样,是先得到ID(ID又是从EPROCESS中得到,所以先得到PEPROCESS),再用ZwOpenProcess/ZwOpenThread在当前进程句柄表中创建一个句柄。你没仔细看 |
|
7楼#
发布于:2002-06-24 08:42
上面各位兄弟,我要实现的东西见下面的描述,下一贴我给出我的源代码。这段代码一直没有成功,请各位侠继续关注。
Q35 How do I retrieve the \"user name\" for the user performing a given operation? User names, per se, are not a concept of the core OS. Rather, users are tracked internally as \"security identifiers\" or SIDs. It is possible to extract the SID of the current thread. If a \"user name\" is needed, a user mode service can be used to convert from the SID to the corresponding text user name. This is done using the Win32 function LookupAccountSid, which is documented in the Platform SDK. The SID of the calling thread can be extracted from its token. This is done by first attempting to open the thread token (ZwOpenThreadTokenEx or NtOpenThreadToken or NtOpenThreadTokenEx). If this fails because the thread has no token, the filter should open the process token (ZwOpenProcessTokenEx or NtOpenProcessToken or NtOpenProcessTokenEx). In either case, the filter will have a handle for a token. The SID can be retrieved from the given token using NtQueryInformationToken or ZwQueryInformationToken. The filter should specify TokenUser as the TOKEN_INFORMATION_CLASS value. The call will return a buffer that contains the TOKEN_USER structure. This structure contains the SID of the token. Note, however, that obtaining the SID of the current caller is often not precisely what a filter is trying to accomplish. Instead, often the filter wishes to know the SID of the requesting thread. For local calls, this will typically be the same. For remote calls, however, the CIFS server routinely utilizes impersonation during IRP_MJ_CREATE and for some IRP_MJ_SET_INFORMATION operations. Otherwise, the CIFS server uses the local system\'s credentials. To handle this case, a filter must store away the credential information of the original caller. In the case of IRP_MJ_CREATE the original caller\'s token is specified as part of the IO_SECURITY_CONTEXT parameter. The ACCESS_STATE structure in turn contains the SECURITY_SUBJECT_CONTEXT and the filter can retrieve a pointer to the token using SeQuerySubjectContextToken. The SID can then be retrieved from the token using SeQueryInformationToken. 这是从OSR网站上摘来的IFS KIT FAQ中的一段。 |
|
|
8楼#
发布于:2002-06-24 08:45
这是我的源代码及相关函数原形说明。
NTSTATUS GetUserName( IN PIRP pIrp ) { NTSTATUS status = STATUS_SUCCESS; HANDLE hProcess; HANDLE TokenHandle; //Get token handle PIO_STACK_LOCATION pThisSP; ACCESS_MASK DesiredAccess; ULONG ReturnLength; PTOKEN_USER TokenInformation; //for SID UNICODE_STRING SidString; CHAR SidStringBuffer[512]; hProcess = PsReferencePrimaryToken( PsGetCurrentProcess() ); if( !hProcess ) return STATUS_INVALID_HANDLE; pThisSP = IoGetCurrentIrpStackLocation( pIrp ); DesiredAccess = pThisSP->Parameters.Create.SecurityContext->DesiredAccess; // // ZwOpenProcessToken 可以用 ObOpenObjectByPointer来代替,都是undocumeted API // status = ZwOpenProcessToken( hProcess, DesiredAccess, &TokenHandle ); if( NT_SUCCESS(status) ) { ZwClose( TokenHandle ); } status = ObOpenObjectByPointer( hProcess, 0, NULL, TOKEN_QUERY, NULL, KernelMode, &TokenHandle ); ObDereferenceObject( hProcess ); if( !NT_SUCCESS(status) ) { // // Try to ZwOpenProcessToken // DbgPrint((\"Can retrieve the otken of current process\")); return status; } TokenInformation = ExAllocatePool( PagedPool, MAXUSERNAMELEN *2); if( !TokenInformation ) { DbgPrint((\"Not enough memory in FileproGetFileUser when try to retrieve user name\")); ZwClose( TokenHandle ); return STATUS_INSUFFICIENT_RESOURCES; } status = NtQueryInformationToken( TokenHandle, TokenUser, TokenInformation, MAXUSERNAMELEN*2, &ReturnLength ); if( !NT_SUCCESS(status) ) { DbgPrint((\" ZwQueryInformationToken error\")); ExFreePool( TokenInformation ); ZwClose( TokenHandle ); return STATUS_UNSUCCESSFUL; } // // Get the SID from the TokenInformation // ZwClose( TokenHandle ); RtlZeroMemory( SidStringBuffer, sizeof(SidStringBuffer) ); SidString.Buffer = (PWCHAR)SidStringBuffer; SidString.MaximumLength = sizeof( SidStringBuffer ); status = RtlConvertSidToUnicodeString( &SidString, TokenInformation->User.Sid, FALSE ); ExFreePool( TokenInformation ); if( !NT_SUCCESS(status) ) { DbgPrint((\"RtlConvertSidToUnicodeString error\")); return status; } return STATUS_SUCCESS; } 相关函数原形说明: typedef struct _TOKEN_USER { SID_AND_ATTRIBUTES User; } TOKEN_USER, *PTOKEN_USER; HANDLE PsReferencePrimaryToken(PEPROCESS Process ); NTSTATUS RtlConvertSidToUnicodeString( PUNICODE_STRING SidString, PVOID Sid, BOOLEAN AllocateString ); NTSTATUS NtQueryInformationToken( HANDLE Token, TOKEN_INFORMATION_CLASS TokenInformationClass, PVOID TokenInformation, ULONG TokenInformationLength, PULONG ReturnLength ); NTSTATUS ObOpenObjectByPointer( PVOID Object, ULONG Flags, PACCESS_STATE AccessState, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PHANDLE Handle ); 请各位大侠帮忙分析!谢谢! |
|
|
9楼#
发布于:2002-06-24 08:47
老兄:你这里得到的并晃是句柄,而是指针。 pjf兄,现在得到进程句柄已经成功,但是在调用NtQueryInformationToken时,status总是返回0xC0000005的错误,我查DDK中得知此错误为STATUS_ACCESS_VIOLATION. |
|
|
10楼#
发布于:2002-06-24 09:34
可能是你的权限还不够吧
|
|
11楼#
发布于:2002-06-24 09:48
可能是你的权限还不够吧
------------------------------------------------------------------------------ hehe,这可是内核程序。 0xC0000005: The instruction at \"0x%08lx\" referenced memory at \"0x%08lx\". The memory could not be \"%s\". 有事,晚上再来看看或许有发现。 |
|
12楼#
发布于:2002-06-24 21:23
ZwOpen*所用的HANDLE与应用程序里用的是一样的,是一给很小的索引值而已,看了一下PsReferencePrimaryToken的返回值为0xE********,显然不是索引,以前分析句柄表,其地址往往在0xE*,所以PsReferencePrimaryToken返回值有可能就是当前进程句柄表或2000系统句柄表中的一项的地址,没去细究。反正不能用于ZwOpen***函数,否则返回总是0xC0000008(错误的句柄)。
应该用ObOpenObjectByPointer。 下面程序段运行试成功的:(为了偷懒,直接把MAXUSERNAMELEN设为很大的4096) NTSTATUS GetUserName(IN PIRP pIrp) { NTSTATUS status = STATUS_SUCCESS; HANDLE hProcess; HANDLE TokenHandle; //Get token handle PIO_STACK_LOCATION pThisSP; ACCESS_MASK DesiredAccess; ULONG ReturnLength; PTOKEN_USER TokenInformation; //for SID UNICODE_STRING SidString; CHAR SidStringBuffer[512]; hProcess = PsReferencePrimaryToken(PsGetCurrentProcess()); if( !hProcess ) return STATUS_INVALID_HANDLE; status = ObOpenObjectByPointer(hProcess, 0, NULL, TOKEN_QUERY, NULL, KernelMode, &TokenHandle ); ObDereferenceObject(hProcess); if( !NT_SUCCESS(status) ) { // // Try to ZwOpenProcessToken // return status; } TokenInformation = (PTOKEN_USER)ExAllocatePool(PagedPool, 4096 *2); if( !TokenInformation ) { DbgPrint((\"Not enough memory in FileproGetFileUser when try to retrieve user name\")); return STATUS_INSUFFICIENT_RESOURCES; } status = ZwQueryInformationToken(TokenHandle, TokenUser, TokenInformation, 4096*2, &ReturnLength ); if( !NT_SUCCESS(status) ) { DbgPrint((\" ZwQueryInformationToken error\")); ExFreePool( TokenInformation ); ZwClose( TokenHandle ); return STATUS_UNSUCCESSFUL; } // // Get the SID from the TokenInformation // ZwClose(TokenHandle); RtlZeroMemory( SidStringBuffer, sizeof(SidStringBuffer) ); SidString.Buffer = (PWCHAR)SidStringBuffer; SidString.MaximumLength = sizeof( SidStringBuffer ); status = RtlConvertSidToUnicodeString( &SidString, TokenInformation->User.Sid, FALSE ); ExFreePool( TokenInformation ); if( !NT_SUCCESS(status) ) { DbgPrint((\"RtlConvertSidToUnicodeString error\")); return status; } return STATUS_SUCCESS; } 我运行的环境是一个普通驱动的Dispacth例程,若你的环境比较特殊可能会失败。你原先返回值很奇怪,我这没碰到过。 |
|
13楼#
发布于:2002-06-24 22:03
hProcess = PsReferencePrimaryToken(PsGetCurrentProcess());
-------------------------------------------------------------------------------- 这里的hProcess写为Process_Token_Point更准确吧,你再看看。忙死了,没时间细究。 |
|
14楼#
发布于:2002-06-24 22:10
大概看了一下,似乎没错,你写的hProcess是指向Token对象的指针。这个程序段没用上进程句柄呀,你废那么大劲做什么?呵呵
不过要得到句柄除了开始说的应该有简单一点的办法:ObOpenObjectByPointer,第一个参数为PEROCESS. |
|
15楼#
发布于:2002-06-24 22:22
不过要得到句柄除了开始说的应该有简单一点的办法:ObOpenObjectByPointer,第一个参数为PEROCESS
----------------------------------------------------------------------------- 试过了,成。 所以前面的程序又可以改写为先用 status = ObOpenObjectByPointer(PsGetCurrentProcess(), 0, NULL, TOKEN_QUERY, NULL, KernelMode, &hProcess); 在用: status = ZwOpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &TokenHandle ); 我这里是成功的。 |
|
16楼#
发布于:2002-06-25 08:38
谢谢pjf兄,错误原因已经找到。
我犯的错误在这里: 1.我用NtQueryInformationToken调用,结果总是返回错误码0xC0000005(STATUS_ACCESS_VIOLATION),在网上搜索了半天终于发现原因是这样。NtQueryInformationToken和ZwQueryInformationToken虽然都可以在内核中使用,但是还是有区别的,最大的区别在于:NtQueryInformationToken会执行参数的例行检查,查看其对齐方式是否正确。在其内容部ProbeForRead和ProbeForWrite等的调用。而ZwQueryInformationToken不会执行这项检查,所以不会出错。 2.另外,进程句柄在此处被当作了TOKEN,PsReferencePrimaryToken返回的是Token的句柄,没有错。 感谢各位兄弟特别是pjf兄的帮助,我的问题已经解决了。 |
|
|
17楼#
发布于:2002-06-25 12:06
进程句柄在此处被当作了TOKEN,PsReferencePrimaryToken返回的是Token的句柄,没有错
-------------------------------------------------------------------------------- 虽然ntifs.h中PsReferencePrimaryToken的原型定义返回值是HANDLE,但可以确定它返回的是一个内核对象指针,所以又用ObOpenObjectByPointer利用此指针创立了一个句柄。应该所有内核对象都可用ObOpenObjectByPointer来创句柄,挺方便的。 |
|
18楼#
发布于:2002-06-25 12:54
status = NtQueryInformationToken( TokenHandle
---------------------------------------------------------------------------- 没注意你用的是这个,难怪我这老没错了,呵呵 NtQueryInformationToken与ZwQueryInformationToken的区别不在于它多做了什么,而是它少做了一些东西。其实Gary Nebbett提到过。 ZwQueryInformationToken的代码与ntdll.dll导出的同名函数基本上是一样的,都是使用Int2E(对NT/2000而言,新版的微软系统二者不同:一个用sysenter,一个直接call),ZwQueryInformationToken用int2e重入内核最终还是会进入NtQueryInformationToken。 |
|
19楼#
发布于:2002-06-25 14:59
你们说的不完全是同一个东西。
NtQueryInformationToken在ntdll和ntoskrnl中都export出来的。 在ntdll中是完全相同的实现。在ntoskrnl中不一样。 估计link lib的顺序不同导致大家有的出错,有的没有出错。 |
|
上一页
下一页