A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #29016  by myid
 Sat Aug 13, 2016 8:05 am
Hi, everyone.
We all knows that we can use ZwDuplicateObject to "copy" a handle from target process.
Code: Select all
Status = ZwDuplicateObject(hProcess,(HANDLE)HandleValue,NtCurrentProcess(),&hDupObj,0,0,DUPLICATE_SAME_ACCESS);
This code work on XP to WIN8.1 but failed on WIN10(0xC00000BB).Who can tell me a reason.
Thanks a lot.
 #29028  by EP_X0FF
 Sat Aug 13, 2016 1:56 pm
Give us more details please, what is the source process?
 #29031  by myid
 Sat Aug 13, 2016 9:48 pm
EP_X0FF wrote:Give us more details please, what is the source process?
Current process is sytem process.
Here is my code(kernel mode):
Code: Select all
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO{
	USHORT	UniqueProcessId;
	USHORT	CreatorBackTraceIndex;
	UCHAR	ObjectTypeIndex;
	UCHAR	HandleAttributes;
	USHORT	HandleValue;
	PVOID	Object;
	ULONG	GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;

typedef struct _SYSTEM_HANDLE_INFORMATION {
    SIZE_T NumberOfHandles;
	SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

BOOLEAN CloseFileHandleW(WCHAR *szFileName)
{
	BOOLEAN b=0;
	PVOID Buffer=NULL;
	NTSTATUS Status=0;
	SIZE_T i=0, HandleCount=0, LoopCount=0;
	ULONG BufferSize=0x20000;
	PSYSTEM_HANDLE_TABLE_ENTRY_INFO p=NULL;
	Buffer=MALLOC(BufferSize);
	memset(Buffer,0,BufferSize);
	Status = ZwQuerySystemInformation(16, Buffer, BufferSize, 0);	//SystemHandleInformation
	while(Status == 0xC0000004)	//STATUS_INFO_LENGTH_MISMATCH
	{
		FREE(Buffer);
		BufferSize = BufferSize * 2;
		Buffer=MALLOC(BufferSize);
		memset(Buffer,0,BufferSize);
		Status = ZwQuerySystemInformation(16, Buffer, BufferSize, 0);
		LoopCount++;
		if(LoopCount>10)
			break;
	}
	if (!NT_SUCCESS(Status)) 
		return 0;
	HandleCount=((SYSTEM_HANDLE_INFORMATION *)Buffer)->NumberOfHandles;
	p=(SYSTEM_HANDLE_TABLE_ENTRY_INFO *)((SYSTEM_HANDLE_INFORMATION *)Buffer)->Handles;
	//ENUM HANDLEs
	for(i=0;i<HandleCount;i++)
	{
		CLIENT_ID cid={0};
		OBJECT_ATTRIBUTES oa={0};
		OBJECT_BASIC_INFORMATION BasicInfo={0};
		POBJECT_NAME_INFORMATION pNameInfo=NULL;
		HANDLE hProcess=NULL, hDupObj = NULL;
		cid.UniqueProcess = (HANDLE)p[i].UniqueProcessId;
		cid.UniqueThread = (HANDLE)0;
		InitializeObjectAttributes( &oa ,NULL ,0 ,NULL ,NULL );
		Status = ZwOpenProcess(&hProcess ,PROCESS_ALL_ACCESS ,&oa ,&cid);
		if (!NT_SUCCESS(Status))
		{
			DbgPrint("[]ZwOpenProcess Failed: %x\n",Status);
			continue;
		}
		Status = ZwDuplicateObject(hProcess,(HANDLE)(p[i].HandleValue),NtCurrentProcess(),&hDupObj,0,0,DUPLICATE_SAME_ACCESS);//FAILED on here, all returns 0xC00000BB.
		if (!NT_SUCCESS(Status))
		{
			DbgPrint("[]ZwDuplicateObject Failed: %x\n",Status);
			ZwClose(hProcess);
			continue;
		}
		//====================
		//no related code...
		//====================
		if(hDupObj)
			ZwClose(hDupObj);
		if(hProcess)
			ZwClose(hProcess);
		if(b)
			break;
	}
	FREE(Buffer);
	return b;
}
ALL ZwDuplicateObject calls return 0xC00000BB.
 #29044  by myid
 Tue Aug 16, 2016 3:58 am
EP_X0FF wrote:Give us more details please, what is the source process?
I have resolved this question now.
Use ObReferenceObjectByHandle and ObQueryNameString to get handle name.
 #29087  by Vrtule
 Mon Aug 22, 2016 9:47 pm
Since you sent me a PM asking for help, I assume you still wish to know the answer. To be honest, I spent only a very little time with Windows 10 so I did not ran into this problem yet. Looking at the code, I see two possible, but may-be-wrong, explanations:

1) there is an OB callback registered on the Type object for the object the handle of which you are trying to duplicate. The OB callback can remove certain access rights from the desired access mask. When the callback does this for handles that are created without duplication, "nothing" happens and you potentially get STATUS_ACCESS_DENIED later. I am not sure how the thing behaves for handles that are being duplicated; maybe there is no difference.

2) Windows 10 decided to be more strict on the topic of handle duplication. The System process is actually treated as a protected one. Maybe, the system decided that nhandle duplications into protected processes (from the non-protected ones) are permitted no more. Or something like that. I can look briefly into NtDuplicateObject and maybe, I would see the reason.
 #29128  by myid
 Sun Aug 28, 2016 4:49 pm
Vrtule wrote:Since you sent me a PM asking for help, I assume you still wish to know the answer. To be honest, I spent only a very little time with Windows 10 so I did not ran into this problem yet. Looking at the code, I see two possible, but may-be-wrong, explanations:

1) there is an OB callback registered on the Type object for the object the handle of which you are trying to duplicate. The OB callback can remove certain access rights from the desired access mask. When the callback does this for handles that are created without duplication, "nothing" happens and you potentially get STATUS_ACCESS_DENIED later. I am not sure how the thing behaves for handles that are being duplicated; maybe there is no difference.

2) Windows 10 decided to be more strict on the topic of handle duplication. The System process is actually treated as a protected one. Maybe, the system decided that nhandle duplications into protected processes (from the non-protected ones) are permitted no more. Or something like that. I can look briefly into NtDuplicateObject and maybe, I would see the reason.
Thanks. So I use a new way to bypass access check.