BOOL CALLBACK kull_m_handle_getHandlesOfType_callback(PSYSTEM_HANDLE pSystemHandle, PVOID pvArg) { PHANDLE_ENUM_DATA pData = (PHANDLE_ENUM_DATA) pvArg; BOOL status = TRUE; HANDLE hProcess, hRemoteHandle; POBJECT_TYPE_INFORMATION pInfos; ULONG szNeeded; if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pSystemHandle->ProcessId)) { if(DuplicateHandle(hProcess, (HANDLE) pSystemHandle->Handle, GetCurrentProcess(), &hRemoteHandle, pData->dwDesiredAccess, TRUE, pData->dwOptions)) { if(NtQueryObject(hRemoteHandle, ObjectTypeInformation, NULL, 0, &szNeeded) == STATUS_INFO_LENGTH_MISMATCH) { if(pInfos = (POBJECT_TYPE_INFORMATION) LocalAlloc(LPTR, szNeeded)) { if(NT_SUCCESS(NtQueryObject(hRemoteHandle, ObjectTypeInformation, pInfos, szNeeded, &szNeeded))) { if(!pData->type || RtlEqualUnicodeString(&pInfos->TypeName, pData->type, TRUE)) status = pData->callBack(hRemoteHandle, pSystemHandle, pData->pvArg); } LocalFree(pInfos); } } CloseHandle(hRemoteHandle); } CloseHandle(hProcess); } return status; }
// TitanEngine.Handler[Mutex].functions: __declspec(dllexport) long TITCALL HandlerEnumerateOpenMutexes(HANDLE hProcess, DWORD ProcessId, LPVOID HandleBuffer, DWORD MaxHandleCount) { HANDLE myHandle = NULL; HANDLE copyHandle = NULL; ULONG RequiredSize = NULL; ULONG TotalHandleCount = NULL; unsigned int HandleCount = NULL; PNTDLL_QUERY_HANDLE_INFO HandleInfo; char HandleFullData[0x1000] = {0}; char HandleNameDataB[0x1000] = {0}; LPVOID HandleNameData = HandleNameDataB; PPUBLIC_OBJECT_TYPE_INFORMATION pObjectTypeInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION)HandleFullData; DynBuf hinfo; if(!NtQuerySysHandleInfo(hinfo)) return 0; LPVOID QuerySystemBuffer = hinfo.GetPtr(); RtlMoveMemory(&TotalHandleCount, QuerySystemBuffer, sizeof ULONG); QuerySystemBuffer = (LPVOID)((ULONG_PTR)QuerySystemBuffer + 4); HandleInfo = (PNTDLL_QUERY_HANDLE_INFO)QuerySystemBuffer; while(TotalHandleCount > NULL) { if(HandleInfo->ProcessId == ProcessId && HandleCount < MaxHandleCount) { //if(!(HandleInfo->GrantedAccess & SYNCHRONIZE) || ((HandleInfo->GrantedAccess & SYNCHRONIZE) && ((WORD)HandleInfo->GrantedAccess != 0x19F9))){// && (WORD)HandleInfo->GrantedAccess != 0x89))){ if(HandleInfo->GrantedAccess != 0x0012019F) { if(DuplicateHandle(hProcess, (HANDLE)HandleInfo->hHandle, GetCurrentProcess(), &myHandle, NULL, false, DUPLICATE_SAME_ACCESS)) { RtlZeroMemory(HandleFullData, sizeof(HandleFullData)); NtQueryObject(myHandle, ObjectTypeInformation, HandleFullData, 8, &RequiredSize); NtQueryObject(myHandle, ObjectTypeInformation, HandleFullData, RequiredSize, &RequiredSize); RtlZeroMemory(HandleNameData, 0x1000); if(pObjectTypeInfo->TypeName.Length != NULL) { WideCharToMultiByte(CP_ACP, NULL, (LPCWSTR)pObjectTypeInfo->TypeName.Buffer, -1, (LPSTR)HandleNameData, 0x1000, NULL, NULL); if(lstrcmpiA((LPCSTR)HandleNameData, "Mutant") == NULL) { copyHandle = (HANDLE)HandleInfo->hHandle; RtlMoveMemory(HandleBuffer, ©Handle, sizeof HANDLE); HandleBuffer = (LPVOID)((ULONG_PTR)HandleBuffer + sizeof HANDLE); HandleCount++; } } EngineCloseHandle(myHandle); } } } HandleInfo = (PNTDLL_QUERY_HANDLE_INFO)((ULONG_PTR)HandleInfo + sizeof NTDLL_QUERY_HANDLE_INFO); TotalHandleCount--; } return(HandleCount); }
BOOL CFileControlTool::GetTypeToken( HANDLE h, LPWSTR pszStr,DWORD processId) { ULONG size = 0x2000; UCHAR* lpBuffer = NULL; BOOL ret = FALSE; HANDLE handle; HANDLE hRemoteProcess = NULL; BOOL remote = processId != GetCurrentProcessId(); if ( remote ) { // Open the remote process hRemoteProcess = OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId ); if ( hRemoteProcess == NULL ) return FALSE; // Duplicate the handle DuplicateHandle( hRemoteProcess, h, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS ); } else handle = h; // Query the info size NtQueryObject( handle, 2, NULL, 0, &size ); lpBuffer = new UCHAR[size]; // Query the info size ( type ) if (NtQueryObject( handle, 2, lpBuffer, size, NULL ) == 0 ) { wcscpy(pszStr,(LPCWSTR)(lpBuffer+0x60)); //SystemInfoUtils::LPCWSTR2CString( (LPCWSTR)(lpBuffer+0x60),pszStr); ret = TRUE; } if ( remote ) { if ( hRemoteProcess != NULL ) CloseHandle( hRemoteProcess ); if ( handle != NULL ) CloseHandle( handle ); } if (lpBuffer != NULL) { delete [] lpBuffer; lpBuffer = NULL; } return ret; }
void RegistryMonitor::initialiseObjectNameMap() { HKEY hTestKey; wchar_t szTemp[256]; DWORD dwError = RegOpenCurrentUser(KEY_READ , &hTestKey); if (dwError == ERROR_SUCCESS ) { NTSTATUS status; DWORD RequiredLength; PPUBLIC_OBJECT_TYPE_INFORMATION t; typedef DWORD (WINAPI *pNtQueryObject)(HANDLE,DWORD,VOID*,DWORD,VOID*); pNtQueryObject NtQueryObject = (pNtQueryObject)GetProcAddress(GetModuleHandle(L"ntdll.dll"), (LPCSTR)"NtQueryObject"); status = NtQueryObject(hTestKey, 1, NULL,0,&RequiredLength); if(status == STATUS_INFO_LENGTH_MISMATCH) { t = (PPUBLIC_OBJECT_TYPE_INFORMATION)VirtualAlloc(NULL, RequiredLength, MEM_COMMIT, PAGE_READWRITE); if(status != NtQueryObject(hTestKey, 1,t,RequiredLength,&RequiredLength)) { ZeroMemory(szTemp, 256); CopyMemory(&szTemp, t->TypeName.Buffer, RequiredLength); // Dont change the order of these ... _Classes should be inserted first // Small bug but who cares wstring temp2 = szTemp; temp2 += L"_CLASSES"; wstring name2 = L"HKCR"; objectNameMap.push_back(ObjectPair(temp2, name2)); wstring temp1 = szTemp; wstring name1 = L"HKCU"; objectNameMap.push_back(ObjectPair(temp1, name1)); wstring temp3 = L"\\REGISTRY\\MACHINE"; wstring name3 = L"HKLM"; objectNameMap.push_back(ObjectPair(temp3, name3)); wstring temp4 = L"\\REGISTRY\\USER"; wstring name4 = L"HKU"; objectNameMap.push_back(ObjectPair(temp4, name4)); wstring temp5 = L"\\Registry\\Machine"; wstring name5 = L"HKLM"; objectNameMap.push_back(ObjectPair(temp5, name5)); } VirtualFree(t, 0, MEM_RELEASE); } } }
NTSTATUS PhpGetObjectName( __in HANDLE ProcessHandle, __in HANDLE Handle, __out PPH_STRING *ObjectName ) { NTSTATUS status; POBJECT_NAME_INFORMATION buffer; ULONG bufferSize; ULONG attempts = 8; bufferSize = 0x200; buffer = PhAllocate(bufferSize); // A loop is needed because the I/O subsystem likes to give us the wrong return lengths... do { if (KphIsConnected()) { status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectNameInformation, buffer, bufferSize, &bufferSize ); } else { status = NtQueryObject( Handle, ObjectNameInformation, buffer, bufferSize, &bufferSize ); } if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_BUFFER_TOO_SMALL) { PhFree(buffer); buffer = PhAllocate(bufferSize); } else { break; } } while (--attempts); if (NT_SUCCESS(status)) { *ObjectName = PhCreateStringEx(buffer->Name.Buffer, buffer->Name.Length); } PhFree(buffer); return status; }
/* * @implemented */ BOOL WINAPI GetHandleInformation (HANDLE hObject, LPDWORD lpdwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; DWORD Flags; // hObject = TranslateStdHandle(hObject); Status = NtQueryObject (hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (NT_SUCCESS(Status)) { Flags = 0; if (HandleInfo.Inherit) Flags |= HANDLE_FLAG_INHERIT; if (HandleInfo.ProtectFromClose) Flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE; *lpdwFlags = Flags; return TRUE; } else { SetLastErrorByStatus (Status); return FALSE; } }
BOOL NtQueryObject_ObjectTypeInformation() { typedef NTSTATUS (WINAPI *pNtQueryObject)(IN HANDLE, IN UINT, OUT PVOID, IN ULONG, OUT PULONG); typedef NTSTATUS(WINAPI *pNtCreateDebugObject)(OUT PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES, IN ULONG); pNtQueryObject NtQueryObject = NULL; pNtCreateDebugObject NtCreateDebugObject = NULL; HANDLE DebugObjectHandle; OBJECT_ATTRIBUTES ObjectAttributes; InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0); BYTE memory[0x1000] = { 0 }; POBJECT_TYPE_INFORMATION ObjectInformation = (POBJECT_TYPE_INFORMATION)memory; NTSTATUS Status; HMODULE hNtdll = LoadLibrary(_xor_(_T("ntdll.dll")).c_str()); if (hNtdll == NULL) { } NtCreateDebugObject = (pNtCreateDebugObject)GetProcAddress(hNtdll, _xor_("NtCreateDebugObject").c_str()); if (NtCreateDebugObject == NULL) { } NtCreateDebugObject(&DebugObjectHandle, DEBUG_ALL_ACCESS, &ObjectAttributes, FALSE); if (NtCreateDebugObject) { HMODULE hNtdll = LoadLibrary(_xor_(_T("ntdll.dll")).c_str()); if (hNtdll == NULL) { } NtQueryObject = (pNtQueryObject)GetProcAddress(hNtdll, _xor_("NtQueryObject").c_str()); if (NtCreateDebugObject == NULL) { } Status = NtQueryObject(DebugObjectHandle, ObjectTypeInformation, ObjectInformation, sizeof(memory), 0); CloseHandle(DebugObjectHandle); if (Status >= 0) { if (ObjectInformation->TotalNumberOfObjects == 0) return TRUE; else return FALSE; } else { return FALSE; } } else return FALSE; }
/*++ * @name UnProtectHandle * @implemented NT5.2 * * The UnProtectHandle routine unprotects an object handle against closure. * * @return TRUE or FALSE. * * @remarks None. * *--*/ BOOLEAN NTAPI UnProtectHandle(IN HANDLE ObjectHandle) { NTSTATUS Status; OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; /* Query current state */ Status = NtQueryObject(ObjectHandle, ObjectHandleFlagInformation, &HandleInfo, sizeof(HandleInfo), NULL); if (NT_SUCCESS(Status)) { /* Disable protect from close */ HandleInfo.ProtectFromClose = FALSE; Status = NtSetInformationObject(ObjectHandle, ObjectHandleFlagInformation, &HandleInfo, sizeof(HandleInfo)); if (NT_SUCCESS(Status)) return TRUE; } /* We failed to or set the state */ return FALSE; }
static int vice_ismsystty(int fd) { intptr_t h_stdin = _get_osfhandle(fd); char ntfn_bytes[sizeof(OBJECT_NAME_INFORMATION) + 256 * sizeof(WCHAR)]; OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION*) ntfn_bytes; NTSTATUS status; ULONG ntfn_size = sizeof(ntfn_bytes); USHORT i, l; wchar_t c, *s0; memset(ntfn, 0, ntfn_size); status = NtQueryObject((HANDLE)h_stdin, ObjectNameInformation, ntfn, ntfn_size, &ntfn_size); if (!NT_SUCCESS(status)) { return 0; } l = ntfn->Name.Length; s0 = ntfn->Name.Buffer; /* Check for "\Device\NamedPipe" */ { USHORT l1 = l; wchar_t *s1 = s0; wchar_t expect[] = L"\\Device\\NamedPipe\\"; if (s0[0] == '\\' && s0[1] == '\\' && s0[2] == '?' && s0[3] == '\\') { l1 -= 4; s1 += 4; } for (i = 0; i < l1; i++) { wchar_t e = expect[i]; c = s1[i]; if (!e) { break; } if (c != e) { return 0; } } } /* Look for "-pty%d-" */ for (i = 0; i < l; i++) { c = s0[i]; if (c == '-') { wchar_t *s = s0 + i + 1; if (s[0] == 'p' && s[1] == 't' && s[2] == 'y' && (c = s[3]) && (c >= '0') && (c <= '9')) { s += 4; while ((c = *s) && (c >= '0') && (c <= '9')) { s++; } if (c == '-' || c == 0) { return 1; } } } } return 0; }
BOOLEAN xProtectHandle( HANDLE hObject ) { NTSTATUS Status; OBJECT_HANDLE_FLAG_INFORMATION HandleInfo; Status = NtQueryObject( hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof( HandleInfo ), NULL ); if (NT_SUCCESS( Status )) { HandleInfo.ProtectFromClose = TRUE; Status = NtSetInformationObject( hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof( HandleInfo ) ); if (NT_SUCCESS( Status )) { return TRUE; } } return FALSE; }
static void detect_msys_tty(int fd) { ULONG result; BYTE buffer[1024]; POBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer; PWSTR name; /* check if fd is a pipe */ HANDLE h = (HANDLE) _get_osfhandle(fd); if (GetFileType(h) != FILE_TYPE_PIPE) return; /* get pipe name */ if (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation, buffer, sizeof(buffer) - 2, &result))) return; name = nameinfo->Name.Buffer; name[nameinfo->Name.Length / sizeof(*name)] = 0; /* * Check if this could be a MSYS2 pty pipe ('msys-XXXX-ptyN-XX') * or a cygwin pty pipe ('cygwin-XXXX-ptyN-XX') */ if ((!wcsstr(name, L"msys-") && !wcsstr(name, L"cygwin-")) || !wcsstr(name, L"-pty")) return; if (fd == 2) setvbuf(stderr, NULL, _IONBF, BUFSIZ); fd_is_interactive[fd] |= FD_MSYS; }
void CheckBlockThreadFunc(void* param) { _NtQueryObject NtQueryObject = (_NtQueryObject)GetProcAddress(GetModuleHandleA("NtDll.dll"), "NtQueryObject"); if (NtQueryObject != NULL) { PVOID objectNameInfo = NULL; ULONG returnLength; objectNameInfo = malloc(0x1000); NtQueryObject((HANDLE)param, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength); } }
NTSTATUS NTAPI NtCloseHook(IN HANDLE Handle) { char info[16]; if (NtQueryObject(Handle, (OBJECT_INFORMATION_CLASS)4, &info, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), nullptr) >= 0) { return origClose(Handle); } return STATUS_INVALID_HANDLE; }
/* * @implemented */ BOOL WINAPI SetHandleInformation(IN HANDLE hObject, IN DWORD dwMask, IN DWORD dwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; hObject = TranslateStdHandle(hObject); if (IsConsoleHandle(hObject)) { /* FIXME: SetConsoleHandleInformation required */ UNIMPLEMENTED; BaseSetLastNTError(STATUS_NOT_IMPLEMENTED); return FALSE; } Status = NtQueryObject(hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return FALSE; } if (dwMask & HANDLE_FLAG_INHERIT) { HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) != 0; } if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) { HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0; } Status = NtSetInformationObject(hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(HandleInfo)); if (NT_SUCCESS(Status)) return TRUE; BaseSetLastNTError(Status); return FALSE; }
NTSTATUS PhpGetObjectBasicInformation( __in HANDLE ProcessHandle, __in HANDLE Handle, __out POBJECT_BASIC_INFORMATION BasicInformation ) { NTSTATUS status; if (KphIsConnected()) { status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectBasicInformation, BasicInformation, sizeof(OBJECT_BASIC_INFORMATION), NULL ); if (NT_SUCCESS(status)) { // The object was referenced in KProcessHacker, so // we need to subtract 1 from the pointer count. BasicInformation->PointerCount -= 1; } } else { status = NtQueryObject( Handle, ObjectBasicInformation, BasicInformation, sizeof(OBJECT_BASIC_INFORMATION), NULL ); if (NT_SUCCESS(status)) { // The object was referenced in NtQueryObject and // a handle was opened to the object. We need to // subtract 1 from the pointer count, then subtract // 1 from both counts. BasicInformation->HandleCount -= 1; BasicInformation->PointerCount -= 2; } } return status; }
/* * supGetObjectTypesInfo * * Purpose: * * Returns buffer with system types information. * * Returned buffer must be freed with HeapFree after usage. * Function will return error after 100 attempts. * */ PVOID supGetObjectTypesInfo( VOID ) { INT c = 0; PVOID Buffer = NULL; ULONG Size = 0x1000; NTSTATUS status; ULONG memIO; do { Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)Size); if (Buffer != NULL) { status = NtQueryObject(NULL, ObjectTypesInformation, Buffer, Size, &memIO); } else { return NULL; } if (NT_SUCCESS(status)) { break; } else { Size = memIO; HeapFree(GetProcessHeap(), 0, Buffer); Buffer = NULL; } c++; if (c > 100) { status = STATUS_SECRET_TOO_LONG; break; } } while (status != STATUS_SUCCESS); if (NT_SUCCESS(status)) { return Buffer; } if (Buffer) { HeapFree(GetProcessHeap(), 0, Buffer); } return NULL; }
/* * @implemented */ BOOL WINAPI SetHandleInformation (HANDLE hObject, DWORD dwMask, DWORD dwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; hObject = TranslateStdHandle(hObject); Status = NtQueryObject (hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (NT_SUCCESS(Status)) { if (dwMask & HANDLE_FLAG_INHERIT) HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) != 0; if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0; Status = NtSetInformationObject (hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION)); if(!NT_SUCCESS(Status)) { SetLastErrorByStatus (Status); return FALSE; } return TRUE; } else { SetLastErrorByStatus (Status); return FALSE; } }
static VOID VerifyAccess_( _In_ HANDLE Handle, _In_ ACCESS_MASK ExpectedAccess, _In_ PCSTR File, _In_ INT Line) { NTSTATUS Status; OBJECT_BASIC_INFORMATION BasicInfo; ULONG Length; Status = NtQueryObject(Handle, ObjectBasicInformation, &BasicInfo, sizeof(BasicInfo), &Length); ok_(File, Line)(Status == STATUS_SUCCESS, "NtQueryObject returned 0x%lx\n", Status); ok_(File, Line)(BasicInfo.GrantedAccess == ExpectedAccess, "GrantedAccess is 0x%lx, expected 0x%lx\n", BasicInfo.GrantedAccess, ExpectedAccess); }
/* * @implemented */ BOOL WINAPI GetHandleInformation(IN HANDLE hObject, OUT LPDWORD lpdwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; DWORD Flags; hObject = TranslateStdHandle(hObject); if (IsConsoleHandle(hObject)) { /* FIXME: GetConsoleHandleInformation required */ UNIMPLEMENTED; BaseSetLastNTError(STATUS_NOT_IMPLEMENTED); return FALSE; } Status = NtQueryObject(hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return FALSE; } Flags = 0; if (HandleInfo.Inherit) Flags |= HANDLE_FLAG_INHERIT; if (HandleInfo.ProtectFromClose) Flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE; *lpdwFlags = Flags; return TRUE; }
bool search::generate_pbo_list() { NTSTATUS status; PSYSTEM_HANDLE_INFORMATION handleInfo; ULONG handleInfoSize = 0x10000; ULONG pid; HANDLE processHandle; ULONG i; _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); if (!NtQuerySystemInformation || !NtDuplicateObject || !NtQueryObject) return false; pid = GetCurrentProcessId(); processHandle = GetCurrentProcess(); handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); while ((status = NtQuerySystemInformation( SystemHandleInformation, handleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { LOG(ERROR) << "Error opening object for pbo search"; free(handleInfo); return false; } for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; /* Check if this handle belongs to the PID the user specified. */ if (handle.ProcessId != pid) continue; /* Duplicate the handle so we can query it. */ if (!NT_SUCCESS(NtDuplicateObject( processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0 ))) { continue; } /* Query the object type. */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ))) { CloseHandle(dupHandle); continue; } /* Query the object name (unless it has an access of 0x0012019f, on which NtQueryObject could hang. */ if (handle.GrantedAccess == 0x0012019f) { free(objectTypeInfo); CloseHandle(dupHandle); continue; } objectNameInfo = malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ))) { /* Reallocate the buffer and try again. */ objectNameInfo = realloc(objectNameInfo, returnLength); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, returnLength, NULL ))) { free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); continue; } } /* Cast our buffer into an UNICODE_STRING. */ objectName = *(PUNICODE_STRING)objectNameInfo; /* Print the information! */ if (objectName.Length) { std::wstring tmp_type(objectTypeInfo->Name.Buffer); std::wstring tmp_name(objectName.Buffer); std::string object_type(tmp_type.begin(), tmp_type.end()); std::string object_name(tmp_name.begin(), tmp_name.end()); if (object_type == "File" && object_name.find(".pbo") != object_name.npos) { char buffer[MAX_PATH]; GetFinalPathNameByHandle(dupHandle, buffer, sizeof(buffer), VOLUME_NAME_DOS); LOG(DEBUG) << "Pbo: " << buffer; _active_pbo_list.push_back(std::string(buffer)); } } free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); } free(handleInfo); return true; }
int wmain(int argc, WCHAR *argv[]) { /* Display welcome message */ printf("handle_monitor %s - Adam Kramer\n", VERSION_NUMBER); /* These variables hold configuration options, which can be altered by arguments passed */ BOOL bIncludeSigned = FALSE; BOOL bSuspendProcess = FALSE; BOOL bVerbose = FALSE; DWORD dNumberCycles = 10; DWORD dHandleChangeThreshold = 10; DWORD dIterationPause = 1000; /* Process arguments */ if (argc > 1) { for (int iNumberArgs = 1; iNumberArgs < argc; iNumberArgs++) { /* /signed - will include signed files in the alerts */ if (!wcscmp(argv[iNumberArgs], L"/signed")) { bIncludeSigned = TRUE; printf("Info: Will show signed files as well as unsigned\n"); } /* /suspect - will attempt to suspend suspicious processes */ else if (!wcscmp(argv[iNumberArgs], L"/suspend")) { bSuspendProcess = TRUE; printf("Info: Will attempt to suspend suspicious processes\n"); } /* /verbose - will display details of iterations and hidden results */ else if (!wcscmp(argv[iNumberArgs], L"/verbose")) { bVerbose = TRUE; printf("Info: Will display verbose status messages\n"); } /* /cycles - allows the user to set cycles completed before analysis */ else if (WCHAR* wSetCycles = wcsstr(argv[iNumberArgs], L"/cycles=")) { wSetCycles = wcschr(wSetCycles, '='); if (!(dNumberCycles = _wtol(++wSetCycles))) { printf("Error: Invalid /cycles parameter\n"); return 1; } printf("Info: Setting number of cycles to %d\n", dNumberCycles); } /* /threshold - allows the user to set the threshold for minimum number of new handles which are suspicious */ else if (WCHAR* wSetThreshold = wcsstr(argv[iNumberArgs], L"/threshold=")) { wSetThreshold = wcschr(wSetThreshold, '='); if (!(dHandleChangeThreshold = _wtol(++wSetThreshold))) { printf("Error: Invalid /threshold parameter\n"); return 1; } printf("Info: Setting handle threshold to %d\n", dHandleChangeThreshold); } /* /pause - allows the user to set a pause between cycles (reduce system load, increase window for finding something) */ else if (WCHAR* wSetPause = wcsstr(argv[iNumberArgs], L"/pause=")) { wSetPause = wcschr(wSetPause, '='); dIterationPause = _wtol(++wSetPause); printf("Info: Setting pause between cycles to %dms\n", dIterationPause); } } /* End of argument processing */ } else { /* No argument passed, accordingly display the usage instructions */ printf("Usage: handle_monitor.exe <optional parameters>\n\n"); printf("Optional parameters:\n"); printf("/cycles=X - Set number of cycles before a review [Default: 10]\n"); printf("/threshold=X - Set suspicion threshold for number of new handles [Default: 10]\n"); printf("/pause=X - Set pause in milliseconds between cycles [Default: 1000]\n"); printf("/signed - Include signed executables in review process\n"); printf("/suspend - Suspend processes identified as suspicious\n"); printf("/verbose - Display verbose progress messages\n\n"); printf("Info: No parameters specified, launching monitoring (Ctrl+C to stop)\n"); } /* Import functions manually from NTDLL */ _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryObject"); /* Master loop! - This runs forever until a user presses Ctrl+C */ for (;;) { /* Update user that process is starting (if /verbose mode activiated) */ if (bVerbose) printf("Verbose Info: Starting sequence\n"); /* Variables used for retrieving handles */ NTSTATUS status; ULONG handleInfoSize = 0x10000; HANDLE processHandle; ULONG i; PSYSTEM_HANDLE_INFORMATION handleInfo; /* Used in each handle iteration to identify the index in iProcessArray of the specific process */ int iCurrentProcess_ArrayIndex = -1; /* Handle array - PROCESS INDEX / HANDLE NUMBER / TEXT OF HANDLE This holds all handles which have been found per process */ auto cHandleArray = new WCHAR[MAX_PROCESSES][MAX_FILE_HANDLES][MAX_PATH](); signed int iProcessArray[MAX_PROCESSES][3] = { 0 }; /* Set process array to -1, which indicates nothing has been set */ for (int j = 0; j < (MAX_PROCESSES - 1); j++) iProcessArray[j][0] = -1; /* Loop dNumberCycles [default: 10] times before analysing result */ for (unsigned int iCycleCounter = 1; iCycleCounter <= dNumberCycles; iCycleCounter++) { handleInfoSize = 0x10000; handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); /* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */ while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { printf("NtQuerySystemInformation failed!\n"); return 1; } /* Loop for each handle on the system, processing it accordingly... */ for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; /* Open a handle to the process associated with the handle */ if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handle.ProcessId))) continue; /* Duplicate the handle so we can query it. */ if (!NT_SUCCESS(NtDuplicateObject(processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, GENERIC_READ, 0, 0))) { CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* Query the object type */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject(dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL))) { free(objectTypeInfo); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* If it's not a file handle, go to next one (as we're only interested in file handles) */ if (wcscmp(objectTypeInfo->Name.Buffer, L"File")) { free(objectTypeInfo); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* Identify the filename from the handle we're looking at */ WCHAR* wHandleFileName = new WCHAR[MAX_PATH](); if (!GetFileNameFromHandle(dupHandle, wHandleFileName)) { free(objectTypeInfo); free(wHandleFileName); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* This is where we add our findings to the database */ iCurrentProcess_ArrayIndex = -1; /* Check whether we've already got an entry for the process we're looking at */ for (int j = 0; j < (MAX_PROCESSES - 1); j++) if (iProcessArray[j][PROCESS_ARRAY_INDEX] == handle.ProcessId) iCurrentProcess_ArrayIndex = j; /* If not, create a new entry for the process associated with the current handle */ if (iCurrentProcess_ArrayIndex == -1) for (int j = 0; j < (MAX_PROCESSES - 1); j++) if (iProcessArray[j][PROCESS_ARRAY_INDEX] == -1) { iProcessArray[j][PROCESS_ARRAY_INDEX] = handle.ProcessId; iCurrentProcess_ArrayIndex = j; break; } /* If there's more than MAX_PROCESSES, throw an error TODO: Tidy this up, identify number of running processes dynamically and set array size accordingly */ if (iCurrentProcess_ArrayIndex == -1) { printf("Error: Too many processes running!\n"); return 1; } /* Look through the handle array, to see whether the filename can be found */ WCHAR cCurrentHandleText[MAX_PATH]; for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) { /* If we hit NULL, there are no more to find, so add ours */ swprintf_s(cCurrentHandleText, MAX_PATH, L"%ls", wHandleFileName); if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")){ wcscpy_s(cHandleArray[iCurrentProcess_ArrayIndex][j], cCurrentHandleText); break; } /* If we find ours, then stop searching */ else if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], cCurrentHandleText)) break; } /* If it's the first (or last) cycle, tally how many entries in the handle array for this particular process we have so far */ if (iCycleCounter == 1) for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")){ iProcessArray[iCurrentProcess_ArrayIndex][PROCESS_ARRAY_COUNT_START_CYCLE] = (j - 1); break; } if (iCycleCounter == dNumberCycles) for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")) { iProcessArray[iCurrentProcess_ArrayIndex][PROCESS_ARRAY_COUNT_END_CYCLE] = (j - 1); break; } free(objectTypeInfo); free(wHandleFileName); CloseHandle(dupHandle); CloseHandle(processHandle); } free(handleInfo); /* If the iteration pause is not 0, sleep for the requested time [Default: 1000ms] */ if (dIterationPause) Sleep(dIterationPause); /* If /verbose active - inform user which cycle we are on */ if (bVerbose) if (iCycleCounter == 1) printf("Verbose Info: Completed cycle %d", iCycleCounter); else if (iCycleCounter == dNumberCycles) printf(" %d\n", iCycleCounter); else printf(" %d", iCycleCounter); } /* If /verbose active - inform user we are now starting a review */ if (bVerbose) printf("Verbose Info: Cycles completed, beginning review\n"); /* Check if any of them met threshold*/ for (int j = 0; j < (MAX_PROCESSES - 1); j++) { if (iProcessArray[j][PROCESS_ARRAY_COUNT_END_CYCLE] < iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE]) continue; /* dHandleDelta is the difference between number of handles for a process from first cycle to the last one */ DWORD dHandleDelta = (iProcessArray[j][PROCESS_ARRAY_COUNT_END_CYCLE] - iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE]); /* Check whether the delta is equal or above the threshold */ if (dHandleDelta >= dHandleChangeThreshold) { HANDLE pHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, iProcessArray[j][PROCESS_ARRAY_INDEX]); TCHAR tProcessName[MAX_PATH]; GetModuleFileNameEx(pHandle, 0, tProcessName, MAX_PATH); CloseHandle(pHandle); /* If we don't want signed, yet it is signed, skip... */ if (!bIncludeSigned && (is_signed(tProcessName) == 0)) { if (bVerbose) wprintf(L"Verbose Info: Skipping alert on %s (%d) despite trigger, as it is signed (use /signed to alert on signed executables too)\n", tProcessName, iProcessArray[j][PROCESS_ARRAY_INDEX]); continue; } /* Inform the user if we have a suspicious process */ wprintf(L"Alert! Process: %s (%d) has had a suspicious number of handles (%d) created in the last cycle\nNew handles created during this cycle:\n", tProcessName, iProcessArray[j][PROCESS_ARRAY_INDEX], dHandleDelta); for (DWORD k = 1; k <= dHandleDelta; k++) wprintf(L"%s\n", cHandleArray[j][iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE] + k]); if (bSuspendProcess) { printf("Info: Attempting to suspend process %d\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); /* Attach debugger to process (freeze it!)*/ if (!DebugActiveProcess(iProcessArray[j][PROCESS_ARRAY_INDEX])) { printf("Info: Could not attach to process %d as a debugger\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); } else { DebugSetProcessKillOnExit(FALSE); printf("Info: Successfully attached to process %d as debugger\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); printf("Info: It will remain frozen until this process is terminated\n"); } } printf("------------------------------------------------------------------------------\n"); } } if (bVerbose) printf("Verbose Info: Review complete\n"); free(cHandleArray); } return 0; }
PyObject* psutil_get_open_files(long pid, HANDLE processHandle) { _NtQuerySystemInformation NtQuerySystemInformation = GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); _NtQueryObject NtQueryObject = GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); NTSTATUS status; PSYSTEM_HANDLE_INFORMATION handleInfo; ULONG handleInfoSize = 0x10000; ULONG i; ULONG fileNameLength; PyObject *filesList = Py_BuildValue("[]"); PyObject *arg = NULL; PyObject *fileFromWchar = NULL; if (filesList == NULL) return NULL; handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); if (handleInfo == NULL) { Py_DECREF(filesList); PyErr_NoMemory(); return NULL; } /* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */ while ((status = NtQuerySystemInformation( SystemHandleInformation, handleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) { handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); } /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { //printf("NtQuerySystemInformation failed!\n"); Py_DECREF(filesList); free(handleInfo); return NULL; } for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo = NULL; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; fileFromWchar = NULL; arg = NULL; /* Check if this handle belongs to the PID the user specified. */ if (handle.ProcessId != pid) continue; /* Skip handles with the following access codes as the next call to NtDuplicateObject() or NtQueryObject() might hang forever. */ if((handle.GrantedAccess == 0x0012019f) || (handle.GrantedAccess == 0x001a019f) || (handle.GrantedAccess == 0x00120189) || (handle.GrantedAccess == 0x00100000)) { continue; } /* Duplicate the handle so we can query it. */ if (!NT_SUCCESS(NtDuplicateObject( processHandle, handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0 ))) { //printf("[%#x] Error!\n", handle.Handle); continue; } /* Query the object type. */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ))) { //printf("[%#x] Error!\n", handle.Handle); free(objectTypeInfo); CloseHandle(dupHandle); continue; } objectNameInfo = malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ))) { /* Reallocate the buffer and try again. */ objectNameInfo = realloc(objectNameInfo, returnLength); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, returnLength, NULL ))) { /* We have the type name, so just display that.*/ /* printf( "[%#x] %.*S: (could not get name)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); */ free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); continue; } } /* Cast our buffer into an UNICODE_STRING. */ objectName = *(PUNICODE_STRING)objectNameInfo; /* Print the information! */ if (objectName.Length) { /* The object has a name. Make sure it is a file otherwise ignore it */ fileNameLength = objectName.Length / 2; if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) { //printf("%.*S\n", objectName.Length / 2, objectName.Buffer); fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer, fileNameLength); if (fileFromWchar == NULL) goto error_py_fun; #if PY_MAJOR_VERSION >= 3 arg = Py_BuildValue("N", PyUnicode_AsUTF8String(fileFromWchar)); #else arg = Py_BuildValue("N", PyUnicode_FromObject(fileFromWchar)); #endif if (!arg) goto error_py_fun; Py_XDECREF(fileFromWchar); fileFromWchar = NULL; if (PyList_Append(filesList, arg)) goto error_py_fun; Py_XDECREF(arg); } /* printf( "[%#x] %.*S: %.*S\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer, objectName.Length / 2, objectName.Buffer ); */ } else { /* Print something else. */ /* printf( "[%#x] %.*S: (unnamed)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); */ ;; } free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); } free(handleInfo); CloseHandle(processHandle); return filesList; error_py_fun: Py_XDECREF(arg); Py_XDECREF(fileFromWchar); Py_DECREF(filesList); return NULL; }
BOOL CFileControlTool::GetNameByType( HANDLE h, WORD type,LPTSTR str, DWORD processId ) { ULONG size = 0x2000; UNICODE_STRING* lpBuffer = NULL; BOOL ret = FALSE; HANDLE handle; HANDLE hRemoteProcess = NULL; BOOL remote = processId != GetCurrentProcessId(); DWORD dwId = 0; if ( remote ) { hRemoteProcess = OpenProcess(PROCESS_DUP_HANDLE,TRUE,processId); if ( hRemoteProcess == NULL ) return FALSE; DuplicateHandle(hRemoteProcess,h,GetCurrentProcess(),&handle,0,FALSE,DUPLICATE_SAME_ACCESS); } else handle = h; // let's be happy, handle is in our process space, so query the infos :) switch( type ) { case OB_TYPE_PROCESS: GetProcessId( handle, dwId ); _stprintf(str, _T("PID: 0x%X"), dwId ); ret = TRUE; goto cleanup; break; case OB_TYPE_THREAD: GetProcessId( handle, dwId ); _stprintf(str,_T("TID: 0x%X") , dwId ); ret = TRUE; goto cleanup; break; case OB_TYPE_FILE: ret = GetFileName( handle, str ); // access denied :( if ( ret && '\0' == str[0]) goto cleanup; break; }; NtQueryObject ( handle, 1, NULL, 0, &size ); // let's try to use the default if ( size == 0 ) size = 0x2000; lpBuffer = (UNICODE_STRING *)new UCHAR[size]; if ( NtQueryObject( handle, 1, lpBuffer, size, NULL ) == 0 ) { wcscpy(lpBuffer->Buffer,str); //SystemInfoUtils::Unicode2CString( (UNICODE_STRING*)lpBuffer, str ); ret = TRUE; } cleanup: if ( remote ) { if ( hRemoteProcess != NULL ) CloseHandle( hRemoteProcess ); if ( handle != NULL ) CloseHandle( handle ); } if ( lpBuffer != NULL ) { delete [] lpBuffer; lpBuffer = NULL; } return ret; }
/* * propSetDefaultInfo * * Purpose: * * Set information values for Basic page window, obtained from NtQueryObject calls * * ObjectBasicInformation and ObjectTypeInformation used * */ VOID propSetDefaultInfo( _In_ PROP_OBJECT_INFO *Context, _In_ HWND hwndDlg, _In_ HANDLE hObject ) { BOOL cond = FALSE; INT i; HWND hwndCB; NTSTATUS status; ULONG bytesNeeded; WCHAR szBuffer[100]; OBJECT_BASIC_INFORMATION obi; POBJECT_TYPE_INFORMATION TypeInfo = NULL; if ((hObject == NULL) || (Context == NULL)) { return; } // // Query object basic information. // RtlSecureZeroMemory(&obi, sizeof(obi)); status = NtQueryObject(hObject, ObjectBasicInformation, &obi, sizeof(OBJECT_BASIC_INFORMATION), &bytesNeeded); if (NT_SUCCESS(status)) { //Reference Count RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); u64tostr(obi.PointerCount, szBuffer); SetDlgItemText(hwndDlg, ID_OBJECT_REFC, szBuffer); //Handle Count RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); u64tostr(obi.HandleCount, szBuffer); SetDlgItemText(hwndDlg, ID_OBJECT_HANDLES, szBuffer); //NonPagedPoolCharge RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); u64tostr(obi.NonPagedPoolCharge, szBuffer); SetDlgItemText(hwndDlg, ID_OBJECT_NP_CHARGE, szBuffer); //PagedPoolCharge RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); u64tostr(obi.PagedPoolCharge, szBuffer); SetDlgItemText(hwndDlg, ID_OBJECT_PP_CHARGE, szBuffer); //Attributes hwndCB = GetDlgItem(hwndDlg, IDC_OBJECT_FLAGS); if (hwndCB) { SendMessage(hwndCB, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0); EnableWindow(hwndCB, (obi.Attributes > 0) ? TRUE : FALSE); if (obi.Attributes != 0) { for (i = 0; i < 8; i++) { if (GET_BIT(obi.Attributes, i)) SendMessage(hwndCB, CB_ADDSTRING, (WPARAM)0, (LPARAM)T_ObjectFlags[i]); } SendMessage(hwndCB, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); } } } // // Set flag bit for next usage on Type page. // do { bytesNeeded = 0; status = NtQueryObject(hObject, ObjectTypeInformation, NULL, 0, &bytesNeeded); if (bytesNeeded == 0) { SetLastError(RtlNtStatusToDosError(status)); break; } TypeInfo = supHeapAlloc(bytesNeeded + sizeof(ULONG_PTR)); if (TypeInfo == NULL) break; status = NtQueryObject(hObject, ObjectTypeInformation, TypeInfo, bytesNeeded, &bytesNeeded); if (NT_SUCCESS(status)) { if (TypeInfo->SecurityRequired) { SET_BIT(Context->ObjectFlags, 3); } if (TypeInfo->MaintainHandleCount) { SET_BIT(Context->ObjectFlags, 4); } } else { SetLastError(RtlNtStatusToDosError(status)); } } while (cond); if (TypeInfo) { supHeapFree(TypeInfo); } }
/* * propBasicQuerySymlink * * Purpose: * * Set information values for SymbolicLink object type * * If ExtendedInfoAvailable is FALSE then it calls propSetDefaultInfo to set Basic page properties * */ VOID propBasicQuerySymlink( _In_ PROP_OBJECT_INFO *Context, _In_ HWND hwndDlg, _In_ BOOL ExtendedInfoAvailable ) { NTSTATUS status; ULONG bytesNeeded; HANDLE hObject; LPWSTR lpLinkTarget; TIME_FIELDS SystemTime; WCHAR szBuffer[MAX_PATH]; OBJECT_BASIC_INFORMATION obi; SetDlgItemText(hwndDlg, ID_OBJECT_SYMLINK_TARGET, T_CannotQuery); SetDlgItemText(hwndDlg, ID_OBJECT_SYMLINK_CREATION, T_CannotQuery); if (Context == NULL) { return; } // // Open SymbolicLink object. // hObject = NULL; if (!propOpenCurrentObject(Context, &hObject, SYMBOLIC_LINK_QUERY)) { return; } // // Copy link target from main object list for performance reasons. // So we don't need to query same data again. // lpLinkTarget = Context->lpDescription; if (lpLinkTarget) { SetDlgItemText(hwndDlg, ID_OBJECT_SYMLINK_TARGET, lpLinkTarget); } //Query Link Creation Time RtlSecureZeroMemory(&obi, sizeof(OBJECT_BASIC_INFORMATION)); status = NtQueryObject(hObject, ObjectBasicInformation, &obi, sizeof(OBJECT_BASIC_INFORMATION), &bytesNeeded); if (NT_SUCCESS(status)) { FileTimeToLocalFileTime((PFILETIME)&obi.CreationTime, (PFILETIME)&obi.CreationTime); RtlSecureZeroMemory(&SystemTime, sizeof(SystemTime)); RtlTimeToTimeFields((PLARGE_INTEGER)&obi.CreationTime, (PTIME_FIELDS)&SystemTime); //Month starts from 0 index if (SystemTime.Month - 1 < 0) SystemTime.Month = 1; if (SystemTime.Month > 12) SystemTime.Month = 12; RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer)); wsprintf(szBuffer, FORMATTED_TIME_DATE_VALUE, SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.Day, Months[SystemTime.Month - 1], SystemTime.Year); SetDlgItemText(hwndDlg, ID_OBJECT_SYMLINK_CREATION, szBuffer); } // // Query object basic and type info if needed. // if (ExtendedInfoAvailable == FALSE) { propSetDefaultInfo(Context, hwndDlg, hObject); } NtClose(hObject); }
int wmain(int argc, WCHAR *argv[]) { _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); NTSTATUS status; PSYSTEM_HANDLE_INFORMATION handleInfo; ULONG handleInfoSize = 0x10000; ULONG pid = 0; HANDLE processHandle; ULONG i; if (argc < 2) { printf("Usage: handles filepath [pid]\n"); return 1; } if (argc > 2) { pid = _wtoi(argv[2]); } // convert C:\Windows\System32 to \Device\HarddiskVolume1\Windows\System32 const WCHAR* filePath = argv[1]; if (wcslen(filePath) < 2 || filePath[1] != L':') { printf("Can't process input path which is tool short or not contain local driver!\n"); return 1; } PWSTR pDosDriveName = new TCHAR[MAX_PATH]; TCHAR szDrive[3] = TEXT(" :"); szDrive[0] = filePath[0]; DWORD uiLen = QueryDosDeviceW(szDrive, pDosDriveName, MAX_PATH); if (0 == uiLen) { if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { printf("QueryDosDeviceW failed: %d\n", GetLastError()); return 1; } delete[]pDosDriveName; pDosDriveName = new TCHAR[uiLen + 1]; uiLen = QueryDosDevice(szDrive, pDosDriveName, uiLen + 1); if (0 == uiLen) { printf("QueryDosDeviceW failed: %d\n", GetLastError()); return 1; } } wcscat(pDosDriveName, &filePath[2]); handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); /* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */ while ((status = NtQuerySystemInformation( SystemHandleInformation, handleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { printf("NtQuerySystemInformation failed!\n"); return 1; } for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; // Jump of no file /*if (handle.ObjectTypeNumber != 31) { continue; }*/ /* Check if this handle belongs to the PID the user specified. */ if (pid != 0 && handle.ProcessId != pid) continue; if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handle.ProcessId))) { //printf("Could not open PID %d! (Don't try to open a system process.)\n", handle.ProcessId); continue; } /* Duplicate the handle so we can query it. */ DWORD re = NtDuplicateObject( processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0 ); if (ERROR_SUCCESS != re) { printf("[%#x] Error!\n", handle.Handle); continue; } /* Query the object type. */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ))) { printf("[%#x] Error!\n", handle.Handle); CloseHandle(dupHandle); continue; } /* Query the object name (unless it has an access of 0x0012019f, on which NtQueryObject could hang. */ if (handle.GrantedAccess == 0x0012019f) { /* We have the type, so display that. */ printf( "[%#x] %.*S: (did not get name)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); free(objectTypeInfo); CloseHandle(dupHandle); continue; } objectNameInfo = malloc(0x1000); if (!NT_SUCCESS(MyNtQueryObject( NtQueryObject, dupHandle, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ))) { /* Reallocate the buffer and try again. */ objectNameInfo = realloc(objectNameInfo, returnLength); if (!NT_SUCCESS(MyNtQueryObject( NtQueryObject, dupHandle, ObjectNameInformation, objectNameInfo, returnLength, NULL ))) { /* We have the type name, so just display that. */ printf( "[%#x] %.*S: (could not get name)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); continue; } } /* Cast our buffer into an UNICODE_STRING. */ objectName = *(PUNICODE_STRING)objectNameInfo; /* Print the information! */ if (objectName.Length) { /* The object has a name. */ printf( "[%#x] %.*S: %.*S\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer, objectName.Length / 2, objectName.Buffer ); if (wcscmp(objectName.Buffer, pDosDriveName) == 0) { printf("opend by process: %d", handle.ProcessId); break; } } else { /* Print something else. */ printf( "[%#x] %.*S: (unnamed)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); } free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); } free(handleInfo); CloseHandle(processHandle); return 0; }
BOOL NtQueryObject_ObjectAllTypesInformation() { // Function Pointer Typedef for NtQueryObject typedef NTSTATUS(WINAPI *pNtQueryObject)(IN HANDLE, IN UINT, OUT PVOID, IN ULONG, OUT PULONG); // Function pointer Typedef for NtCreateDebugObject typedef NTSTATUS(WINAPI *pNtCreateDebugObject)(OUT PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES, IN ULONG); // We have to import the function pNtQueryObject NtQueryObject = NULL; pNtCreateDebugObject NtCreateDebugObject = NULL; // Some vars ULONG size; PVOID pMemory = NULL; POBJECT_ALL_INFORMATION pObjectAllInfo = NULL; NTSTATUS Status; HMODULE hNtdll = LoadLibrary(_T("ntdll.dll")); if (hNtdll == NULL) { // Handle however.. chances of this failing // is essentially 0 however since // ntdll.dll is a vital system resource } NtQueryObject = (pNtQueryObject)GetProcAddress(hNtdll, "NtQueryObject"); if (NtCreateDebugObject == NULL) { // Handle however it fits your needs but as before, // if this is missing there are some SERIOUS issues with the OS } // Get the size of the information needed Status = NtQueryObject(NULL, 3, &size, sizeof(ULONG), &size); // Alocate memory for the list pMemory = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (pMemory == NULL) return FALSE; // Now we can actually retrieve the list Status = NtQueryObject((HANDLE)-1, 3, pMemory, size, NULL); // Status != STATUS_SUCCESS if (Status != 0x00000000) { VirtualFree(pMemory, 0, MEM_RELEASE); return FALSE; } // We have the information we need pObjectAllInfo = (POBJECT_ALL_INFORMATION)pMemory; UCHAR *pObjInfoLocation = (UCHAR*)pObjectAllInfo->ObjectTypeInformation; ULONG NumObjects = pObjectAllInfo->NumberOfObjects; for (UINT i = 0; i < NumObjects; i++) { POBJECT_TYPE_INFORMATION pObjectTypeInfo = (POBJECT_TYPE_INFORMATION)pObjInfoLocation; // The debug object will always be present if (StrCmp(_T("DebugObject"), pObjectTypeInfo->TypeName.Buffer) == 0) { // Are there any objects? if (pObjectTypeInfo->TotalNumberOfObjects > 0) { VirtualFree(pMemory, 0, MEM_RELEASE); return TRUE; } else { VirtualFree(pMemory, 0, MEM_RELEASE); return FALSE; } } // Get the address of the current entries // string so we can find the end pObjInfoLocation = (unsigned char*)pObjectTypeInfo->TypeName.Buffer; // Add the size pObjInfoLocation += pObjectTypeInfo->TypeName.Length; // Skip the trailing null and alignment bytes ULONG tmp = ((ULONG)pObjInfoLocation) & -4; // Not pretty but it works pObjInfoLocation = ((unsigned char*)tmp) + sizeof(unsigned long); } VirtualFree(pMemory, 0, MEM_RELEASE); return TRUE; }
BOOL GetProcessIdByMutantName(LPCWSTR mutant_name, std::vector<ULONG> &pids) { _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetLibraryProcAddress(TEXT("ntdll.dll"), "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress(TEXT("ntdll.dll"), "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetLibraryProcAddress(TEXT("ntdll.dll"), "NtQueryObject"); if (NtQuerySystemInformation == NULL || NtDuplicateObject == NULL || NtQueryObject == NULL) { return FALSE; } PSYSTEM_HANDLE_INFORMATION handle_info; ULONG handle_info_size = 0x10000; CHeapPtr<UCHAR> handle_info_buffer; handle_info_buffer.Allocate(handle_info_size); NTSTATUS ns; while ((ns = NtQuerySystemInformation( SystemHandleInformation, handle_info_buffer.m_pData, handle_info_size, NULL )) == STATUS_INFO_LENGTH_MISMATCH) { handle_info_buffer.Reallocate(handle_info_size *= 2); } if (!NT_SUCCESS(ns)) { return FALSE; } handle_info = (PSYSTEM_HANDLE_INFORMATION)handle_info_buffer.m_pData; ULONG process_id = 0; HANDLE cur_handle = NULL; for (ULONG i = 0; i < handle_info->HandleCount; i++) { SYSTEM_HANDLE handle = handle_info->Handles[i]; ULONG info_size = 0x1000; if (handle.GrantedAccess == 0x0012019f) { continue; } if (process_id != handle.ProcessId) { process_id = handle.ProcessId; if (cur_handle != NULL) { CloseHandle(cur_handle); cur_handle = NULL; } if (cur_handle == NULL) { cur_handle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, process_id); } if (cur_handle == NULL) { continue; } } HANDLE dup_handle = NULL; if (!NT_SUCCESS(NtDuplicateObject( cur_handle, (HANDLE)handle.Handle, GetCurrentProcess(), &dup_handle, 0, 0, 0 ))) { continue; } CHandle auto_handle(dup_handle); CHeapPtr<UCHAR> obj_type_buffer; obj_type_buffer.Allocate(info_size); POBJECT_TYPE_INFORMATION obj_type_info = (POBJECT_TYPE_INFORMATION)obj_type_buffer.m_pData; if (!NT_SUCCESS(NtQueryObject( dup_handle, ObjectTypeInformation, obj_type_info, info_size, NULL ))) { continue; } if (memcmp(obj_type_info->Name.Buffer, L"Mutant", 12) != 0) { continue; } CHeapPtr<UCHAR> obj_name_buffer; obj_name_buffer.Allocate(info_size); PVOID obj_name_info = obj_name_buffer.m_pData; ULONG return_length; if (!NT_SUCCESS(NtQueryObject( dup_handle, ObjectNameInformation, obj_name_info, info_size, &return_length ))) { continue; } UNICODE_STRING object_name = *(PUNICODE_STRING)obj_name_info; if (object_name.Length) { CStringW object_name(object_name.Buffer, object_name.Length / 2); if (object_name == mutant_name) { pids.push_back(process_id); } //wprintf(L"%u %s\n", process_id, object_name.GetString()); } } if (cur_handle != NULL) { CloseHandle(cur_handle); cur_handle = NULL; } return TRUE; }
VOID TestParent( VOID ) { NTSTATUS Status; STRING DirectoryName; STRING LinkName; STRING LinkTarget; STRING SectionName; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE DirectoryHandle, LinkHandle, SectionHandle; ULONG ReturnedLength; CHAR ObjectInfoBuffer[ 512 ]; OBJECT_BASIC_INFORMATION ObjectBasicInfo; POBJECT_NAME_INFORMATION ObjectNameInfo; POBJECT_TYPE_INFORMATION ObjectTypeInfo; LARGE_INTEGER SectionSize; Status = STATUS_SUCCESS; DbgPrint( "Entering Object Manager User Mode Test Program\n" ); RtlInitString( &SectionName, "\\A:\\OSO001.MSG" ); InitializeObjectAttributes( &ObjectAttributes, &SectionName, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, NULL, NULL ); SectionSize.LowPart = 0x1000; SectiinSize.HighPart = 0; Status = NtCreateSection( &SectionHandle, GENERIC_READ, &ObjectAttributes, &SectionSize, PAGE_READONLY, SEC_RESERVE, NULL ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to create %Z section object (%X) [OK]\n", &SectionName, Status ); } RtlInitString( &DirectoryName, "\\Drives" ); InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, (PSECURITY_DESCRIPTOR)1 ); ObjectAttributes.Length = 0; Status = NtCreateDirectoryObject( &DirectoryHandle, -1, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to create %Z directory object (%X) [OK]\n", &DirectoryName, Status ); } RtlInitString( &DirectoryName, "\\Drives" ); InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, (PSECURITY_DESCRIPTOR)1 ); ObjectAttributes.Length = 0; Status = NtCreateDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to create %Z directory object (%X) [OK]\n", &DirectoryName, Status ); } InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, -1, NULL, (PSECURITY_DESCRIPTOR)1 ); Status = NtCreateDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to create %Z directory object (%X) [OK]\n", &DirectoryName, Status ); } InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, (PSECURITY_DESCRIPTOR)1 ); Status = NtCreateDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to create %Z directory object (%X) [OK]\n", &DirectoryName, Status ); } InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL ); Status = NtCreateDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to create %Z directory object (%X)\n", &DirectoryName, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } Status = NtClose( DirectoryHandle ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to close %Z directory object handle - %lx (%X)\n", &DirectoryName, DirectoryHandle, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to open %Z directory object (%X)\n", &DirectoryName, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } Status = NtQueryObject( DirectoryHandle, ObjectBasicInformation, &ObjectBasicInfo, sizeof( ObjectBasicInfo ), &ReturnedLength ); if (!NT_SUCCESS( Status )) { DbgPrint( "NtQueryObject( %lx, ObjectBasicInfo ) failed - Status == %X\n", DirectoryHandle, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } DbgPrint( "NtQueryObject( %lx, ObjectBasicInfo ) returned %lx bytes\n", DirectoryHandle, ReturnedLength ); DbgPrint( " Attributes = %lx\n", ObjectBasicInfo.Attributes ); DbgPrint( " GrantedAccess = %lx\n", ObjectBasicInfo.GrantedAccess ); DbgPrint( " HandleCount = %lx\n", ObjectBasicInfo.HandleCount ); DbgPrint( " PointerCount = %lx\n", ObjectBasicInfo.PointerCount ); DbgPrint( " PagedPoolCharge = %lx\n", ObjectBasicInfo.PagedPoolCharge ); DbgPrint( " NonPagedPoolCharge = %lx\n", ObjectBasicInfo.NonPagedPoolCharge ); DbgPrint( " NameInfoSize = %lx\n", ObjectBasicInfo.NameInfoSize ); DbgPrint( " TypeInfoSize = %lx\n", ObjectBasicInfo.TypeInfoSize ); DbgPrint( " SecurityDescriptorSize = %lx\n", ObjectBasicInfo.SecurityDescriptorSize ); ObjectNameInfo = (POBJECT_NAME_INFORMATION)ObjectInfoBuffer; Status = NtQueryObject( DirectoryHandle, ObjectNameInformation, ObjectNameInfo, sizeof( ObjectInfoBuffer ), &ReturnedLength ); if (!NT_SUCCESS( Status )) { DbgPrint( "NtQueryObject( %lx, ObjectNameInfo ) failed - Status == %X\n", DirectoryHandle, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } DbgPrint( "NtQueryObject( %lx, ObjectNameInfo ) returned %lx bytes\n", DirectoryHandle, ReturnedLength ); DbgPrint( " Name = (%ld,%ld) '%Z'\n", ObjectNameInfo->Name.MaximumLength, ObjectNameInfo->Name.Length, &ObjectNameInfo->Name ); ObjectTypeInfo = (POBJECT_TYPE_INFORMATION)ObjectInfoBuffer; Status = NtQueryObject( DirectoryHandle, ObjectTypeInformation, ObjectTypeInfo, sizeof( ObjectInfoBuffer ), &ReturnedLength ); if (!NT_SUCCESS( Status )) { DbgPrint( "NtQueryObject( %lx, ObjectTypeInfo ) failed - Status == %X\n", DirectoryHandle, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } DbgPrint( "NtQueryObject( %lx, ObjectTypeInfo ) returned %lx bytes\n", DirectoryHandle, ReturnedLength ); DbgPrint( " TypeName = (%ld,%ld) '%Z'\n", ObjectTypeInfo->TypeName.MaximumLength, ObjectTypeInfo->TypeName.Length, &ObjectTypeInfo->TypeName ); RtlInitString( &LinkName, "TestSymbolicLink" ); InitializeObjectAttributes( &ObjectAttributes, &LinkName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ObjectAttributes.RootDirectory = DirectoryHandle; RtlInitString( &LinkTarget, "\\Device\\FileSystem" ); Status = NtCreateSymbolicLinkObject( &LinkHandle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, &LinkTarget ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to create %Z => %Z symbolic link object (%X)\n", &LinkName, &LinkTarget, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } Status = NtClose( DirectoryHandle ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to close %Z directory object handle - %lx (%X)\n", &DirectoryName, DirectoryHandle, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } RtlInitString( &DirTypeName, "Directory" ); RtlInitString( &LinkTypeName, "SymbolicLink" ); DumpObjectDirs( "\\", 0 ); RtlInitString( &LinkName, "TestSymbolicLink" ); InitializeObjectAttributes( &ObjectAttributes, &LinkName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ObjectAttributes.RootDirectory = LinkHandle; Status = NtOpenDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to open %Z directory object (%X) [OK]\n", &DirectoryName, Status ); } Status = NtClose( LinkHandle ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to close %Z symbolic link handle - %lx (%X)\n", &LinkName, LinkHandle, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to open %Z directory object (%X)\n", &DirectoryName, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } Status = NtMakeTemporaryObject( DirectoryHandle ); if (!NT_SUCCESS( Status )) { DbgPrint( "NtMakeTemporaryObject( %lx ) failed - Status == %X\n", DirectoryHandle, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } Status = NtClose( DirectoryHandle ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to close %Z directory object handle - %lx (%X)\n", &DirectoryName, DirectoryHandle, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to open %Z directory object (%X) [OK]\n", &DirectoryName, Status ); } RtlInitString( &DirectoryName, "\\ExclusiveDir" ); InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE | OBJ_EXCLUSIVE, NULL, NULL ); Status = NtCreateDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to create %Z directory object (%X)\n", &DirectoryName, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE | OBJ_EXCLUSIVE, NULL, NULL ); Status = NtOpenDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to open %Z directory object (%X)\n", &DirectoryName, Status ); NtTerminateProcess( NtCurrentProcess(), Status ); } InitializeObjectAttributes( &ObjectAttributes, &DirectoryName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenDirectoryObject( &DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { DbgPrint( "Unable to open %Z directory object (%X) [OK]\n", &DirectoryName, Status ); } DbgPrint( "Exiting Object Manager User Mode Test Program with Status = %X\n", Status ); }
/* * propSecurityConstructor * * Purpose: * * Initialize class object, query type info, Vtbl, AccessTable, object specific methods. * */ HRESULT propSecurityConstructor( _In_ IObjectSecurity *This, _In_ PROP_OBJECT_INFO *Context, _In_ POPENOBJECTMETHOD OpenObjectMethod, _In_opt_ PCLOSEOBJECTMETHOD CloseObjectMethod, _In_ ULONG psiFlags ) { BOOL cond = FALSE; ULONG bytesNeeded = 0L; NTSTATUS status; SIZE_T Size; HRESULT hResult; HANDLE hObject = NULL; SI_ACCESS *TypeAccessTable = NULL; POBJECT_TYPE_INFORMATION TypeInfo = NULL; do { This->OpenObjectMethod = OpenObjectMethod; //if no close method specified, use default if (CloseObjectMethod == NULL) { This->CloseObjectMethod = propDefaultCloseObject; } else { This->CloseObjectMethod = CloseObjectMethod; } if (!This->OpenObjectMethod(Context, &hObject, READ_CONTROL)) { hResult = E_ACCESSDENIED; break; } bytesNeeded = 0; status = NtQueryObject(hObject, ObjectTypeInformation, NULL, 0, &bytesNeeded); if (bytesNeeded == 0) { hResult = HRESULT_FROM_WIN32(RtlNtStatusToDosError(status)); break; } TypeInfo = supHeapAlloc(bytesNeeded); if (TypeInfo == NULL) { hResult = HRESULT_FROM_WIN32(GetLastError()); break; } status = NtQueryObject(hObject, ObjectTypeInformation, TypeInfo, bytesNeeded, &bytesNeeded); if (!NT_SUCCESS(status)) { hResult = HRESULT_FROM_WIN32(RtlNtStatusToDosError(status)); break; } This->GenericMapping = TypeInfo->GenericMapping; This->ValidAccessMask = TypeInfo->ValidAccessMask; supHeapFree(TypeInfo); TypeInfo = NULL; This->lpVtbl = &g_Vtbl; This->ObjectContext = Context; This->hInstance = g_WinObj.hInstance; This->psiFlags = psiFlags; TypeAccessTable = propGetAccessTable(This); //allocate access table Size = (MAX_KNOWN_GENERAL_ACCESS_VALUE + This->dwAccessMax) * sizeof(SI_ACCESS); This->AccessTable = supHeapAlloc(Size); if (This->AccessTable == NULL) { hResult = HRESULT_FROM_WIN32(GetLastError()); break; } //copy object specific access table if it present if (TypeAccessTable && This->dwAccessMax) { supCopyMemory(This->AccessTable, Size, TypeAccessTable, (This->dwAccessMax * sizeof(SI_ACCESS)) ); } if (This->ValidAccessMask & DELETE) { supCopyMemory(&This->AccessTable[This->dwAccessMax++], sizeof(SI_ACCESS), &GeneralAccessValues[0], sizeof(SI_ACCESS)); } if (This->ValidAccessMask & READ_CONTROL) { supCopyMemory(&This->AccessTable[This->dwAccessMax++], sizeof(SI_ACCESS), &GeneralAccessValues[1], sizeof(SI_ACCESS)); } if (This->ValidAccessMask & WRITE_DAC) { supCopyMemory(&This->AccessTable[This->dwAccessMax++], sizeof(SI_ACCESS), &GeneralAccessValues[2], sizeof(SI_ACCESS)); } if (This->ValidAccessMask & WRITE_OWNER) { supCopyMemory(&This->AccessTable[This->dwAccessMax++], sizeof(SI_ACCESS), &GeneralAccessValues[3], sizeof(SI_ACCESS)); } if (This->ValidAccessMask & SYNCHRONIZE) { supCopyMemory(&This->AccessTable[This->dwAccessMax++], sizeof(SI_ACCESS), &GeneralAccessValues[4], sizeof(SI_ACCESS)); } hResult = S_OK; } while (cond); //cleanup This->CloseObjectMethod(This, hObject); if (TypeInfo) { supHeapFree(TypeInfo); } return hResult; }