A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #27612  by kz丶cn
 Mon Jan 11, 2016 1:31 pm
hello ! kernelmode.info !
I'm here again....
My English is not very good do not suggest :roll:

First ,I pass "OpenProcess" get ProcessHandle ,then I pass "ZwQueryInformationProcess"get Process HandleCount.
OpenProcess dwDesiredAccess is PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE
code :
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_DUP_HANDLE, FALSE, pid);

The number of handles returned by ZwQueryInformationProcess is the same as that of the PCHunter;
There is no problem here....
And then I passed DuplicateHandle...
code :
DuplicateHandle(hProcess,TageHandle,GetCurrentProcess(),&hTest,0,FALSE,DUPLICATE_SAME_ACCESS)

Found missing some handles ,The types of these handles are EtwRegistration (Through the ZwQueryObject query to know)
Don't know what's going on...
All Code:
Code: Select all
BOOL EnumHandle(DWORD pid)
{
	HMODULE hNtdll = 0;
	ULONG hNum = 0,ret = 0;//hNum ZwQueryInformationProcess return
	NTSTATUS state = 0;
	HANDLE TageHandle = 0;
	HANDLE hTest = 0;
	ULONG i = 0;
	POBJECT_NAME_INFORMATION ObjName;
	HANDLE hProcess = 0;
	ULONG RetVal = 0;
	POBJECT_TYPE_INFORMATION lpIn;
	ULONG  DupFaNum = 0; //To record the error of the copy handle and to determine the cycle of death.
	ZWQUERYINFORMATIONPROCESS ZwQueryInformationProcess;
	ZWQUERYOBJECT ZwQueryObject;

	hNtdll = GetModuleHandle("ntdll.dll");
	if(hNtdll == NULL)
	{
		printf("hNtdll is null\n");
		return FALSE;
	}

	ZwQueryInformationProcess = (ZWQUERYINFORMATIONPROCESS)GetProcAddress(hNtdll,"ZwQueryInformationProcess");
	ZwQueryObject = (ZWQUERYOBJECT)GetProcAddress(hNtdll,"ZwQueryObject");
	RtlAdjustPrivilege = (RTLADJUSTPRIVILEGE)GetProcAddress(hNtdll,"RtlAdjustPrivilege");

	if(ZwQueryInformationProcess == NULL || ZwQueryObject == NULL || RtlAdjustPrivilege == NULL)
	{
		printf("ZwAPI is null\n");
		return FALSE;
	}

	RtlAdjustPrivilege(20,1,0,&RetVal);//debug
	RtlAdjustPrivilege(19,1,0,&RetVal);

	hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
                            PROCESS_DUP_HANDLE, FALSE, pid);
	if(hProcess==0)
	{
		printf("OpenProcess is null;\n");
		return FALSE;
	}
	
	ObjName = (POBJECT_NAME_INFORMATION)malloc(0x2000);
	if(ObjName == 0)
	{
		printf("malloc is null\n");
		CloseHandle(hProcess);
		return FALSE;
	}
	state = ZwQueryInformationProcess(hProcess,ProcessHandleCount,&hNum,sizeof(hNum),&ret);
	if(!NT_SUCCESS(state))
	{
		printf("state is null\n");
		free(ObjName);
		CloseHandle(hProcess);
		return FALSE;
	}
	
	lpIn = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
	if(lpIn==0)
	{
		free(ObjName);
		CloseHandle(hProcess);
		return FALSE;
	}

	while (i != hNum)
	{
		TageHandle = (HANDLE)((ULONG)TageHandle + 4);
		if(DuplicateHandle(hProcess,TageHandle,GetCurrentProcess(),&hTest,0,FALSE,DUPLICATE_SAME_ACCESS))
		{
			state = ZwQueryObject(hTest,ObjectTypeInformation,lpIn,0x1000,NULL);
			if(!NT_SUCCESS(state))
			{
				CloseHandle(hProcess);
				free(ObjName);
				free(lpIn);
				return FALSE;
			}
			wprintf(L"ObjectType:%wZ---",lpIn->TypeName);
			if(!wcscmp((wchar_t*)lpIn->TypeName.Buffer,L"Key"))
			{
				//printf("Find Key\n");
			}
			state = ZwQueryObject(hTest,ObjectNameInformation,ObjName,0x2000,NULL);
			if(!NT_SUCCESS(state))
			{
				i++;
				continue;
			}
			printf("Handle:0x%x---",(ULONG)TageHandle);
			wprintf(L"HandleName:%wZ\n",ObjName->Name);
			memset(ObjName,0,0x2000);
			i++;
		}else
		{
			DupFaNum++;
		}
		if(DupFaNum>50)//Can only judge the number of failures to avoid the death cycle
			break;

	}

	//EtwRegistration这个类型复制不过来 不知道怎么回事
	printf("\nReal HandleCount:%d---Enum HandleCount:%d\n",hNum,i);
	printf("EtwRegistration Handle Num:%d\n",hNum - i);
	free(ObjName);
	free(lpIn);
	CloseHandle(hProcess);
	return TRUE;
}
My System is win7 x64 ...
Do not know you understand my English....HAHA
 #27616  by Vrtule
 Mon Jan 11, 2016 10:17 pm
Hello,

I assume that DuplicateHandle returns FALSE for handles of EtwRegistration objects. What **GetLastError* tells you in that case?

**DuplicateHandle** may fail because the source handle has exclusive access to the object. Its duplication would broke the exclusivity. I think Windows do not permit such a situation.

Vrtule
 #27617  by Brock
 Tue Jan 12, 2016 1:19 am
GetLastError will likely return ERROR_NOT_SUPPORTED (error code 50). I noticed the same thing a while back when traversing process handle tables in usermode. He can do it from kernel mode like Process Hacker does, it works with all objects
 #27622  by kz丶cn
 Tue Jan 12, 2016 8:34 am
Vrtule wrote:Hello,

I assume that DuplicateHandle returns FALSE for handles of EtwRegistration objects. What **GetLastError* tells you in that case?

**DuplicateHandle** may fail because the source handle has exclusive access to the object. Its duplication would broke the exclusivity. I think Windows do not permit such a situation.

Vrtule
GetLastError return ERROR_NOT_SUPPORTED
It seems that this device does not support read and write
But I'm not going to feel EtwRegistration I intend to judge if the error code is returned to the ERROR_NOT_SUPPORTED that when it is EtwRegistration but this is not the way to get the address.
Thanks
 #27623  by kz丶cn
 Tue Jan 12, 2016 8:40 am
Brock wrote:GetLastError will likely return ERROR_NOT_SUPPORTED (error code 50). I noticed the same thing a while back when traversing process handle tables in usermode. He can do it from kernel mode like Process Hacker does, it works with all objects
I previously found in the user layer to achieve this problem and then I realized in the kernel of a result is the same as really no way to directly traverse the EPROCESS->HandleTable->TableCode
The error code returned is consistent with you, but I feel the EtwRegistration is not too important so I'm going to directly determine the error code if the error code is in error not supported as EtwRegistration the only address this time is obtained by a through EPROCESS->HandleTable-> TableCode the!!!!!!!!! Thanks for reminding me that I didn't notice the error code before

I translated my English and found that I can not understand the Chinese I am directly on the Chinese bar, you should have a translation tool bar..

我先前在用户层实现的 发现这个问题 然后我又在内核中实现了一次 结果一样 实在没有办法就直接遍历EPROCESS->HandleTable->TableCode了
返回的错误代码跟你一致,不过我感觉这个EtwRegistration不太重要 所以打算直接判断错误代码了 如果错误代码是 ERROR_NOT_SUPPORTED 就当成EtwRegistration了 这个时候地址只能通过EPROCESS->HandleTable->TableCode来得到了 !感谢提醒 我先前没有注意到这个错误代码