LarryDalooza Posted April 16, 2008 Posted April 16, 2008 I have the means to introduce functionality for closing handles to processes that are keeping a file "locked". This would allow you to replace stubborn files during software deployment and/or delete BHO type viruses. Alot of the code necessary already exists within AutoIt and would be rather simple to add to an existing function such as ProcessClose() where a full path is passed rather than a process name or PID. I am sure there are issues of safety involved, but I have no first hand experience with the pitfalls of my proposal. So such things could be vetted here before I pursue inclusion of this functionality or development of a UDF. banzai... Lar. AutoIt has helped make me wealthy
Xenobiologist Posted April 16, 2008 Posted April 16, 2008 Hi,you mean something like: http://ccollomb.free.fr/unlocker/Mega Scripts & functions Organize Includes Let Scite organize the include files Yahtzee The game "Yahtzee" (Kniffel, DiceLion) LoginWrapper Secure scripts by adding a query (authentication) _RunOnlyOnThis UDF Make sure that a script can only be executed on ... (Windows / HD / ...) Internet-Café Server/Client Application Open CD, Start Browser, Lock remote client, etc. MultipleFuncsWithOneHotkey Start different funcs by hitting one hotkey different times
LarryDalooza Posted April 16, 2008 Author Posted April 16, 2008 Xenobiologist said: Hi,you mean something like: http://ccollomb.free.fr/unlocker/MegaThis is what I currently use. Used for years. Never occurred to write my own until now.Lar. AutoIt has helped make me wealthy
James Posted April 16, 2008 Posted April 16, 2008 So you want to make your own version of Unlocker? I'm sure MSDN holds the key to understanding your objective. I shall look around for you Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ
James Posted April 16, 2008 Posted April 16, 2008 So here is some code I found for you:expandcollapse popup#include <stdio.h> #include <windows.h> #include <psapi.h> #include <wchar.h> #include <process.h> #include <ntsecapi.h> #include "ntdll.h" #define STATUS_SUCCESS (long)0x00000000L typedef struct _GetFileNameThreadParam { HANDLE hFile; wchar_t* &nbs p; pName; bool &n bsp; rc; } GetFileNameThreadParam; // From device file name to DOS filename BOOL GetFsFileName( wchar_t* lpDeviceFileName, wchar_t* fsFileName ) { BOOL rc = FALSE; WCHAR lpDeviceName[0x1000]; WCHAR lpDrive[3] = L"A:"; // Iterating through the drive letters for (WCHAR actDrive = L'A'; actDrive <= L'Z'; actDrive++ ) { lpDrive[0] = actDrive; // Query the device for the drive letter if ( QueryDosDevice( lpDrive, lpDeviceName, 0x1000 ) != 0 ) { // Network drive? if ( _wcsnicmp( L"\\Device\\LanmanRedirector\\", lpDeviceName, 25 ) == 0 ) { //Mapped network drive char cDriveLetter; DWORD dwParam; WCHAR lpSharedName[0x1000]; if ( swscanf( lpDeviceName, L"\\Device\\ LanmanRedirector\\;%c:%d\\%s", &cDriveLette r, &dwParam, lpSharedName ) != 3 ) continue; wcscpy( lpDeviceName, L"\\Device\\LanmanRedirector\\" ); wcscat( lpDeviceName, lpSharedName ); } // Is this the drive letter we are looking for? if ( _wcsnicmp( lpDeviceName, lpDeviceFileName, wcslen( lpDeviceName ) ) == 0 ) { wchar_t* p = (wchar_t*)( lpDeviceFileName + wcslen(lpDeviceName)); wcscpy(fsFileName,lpDrive); wcscat(fsFileName, p); rc = TRUE; break; } } } return rc; } void mmMsg(wchar_t* message, int exitCode=0) { wprintf(message); //if (!exitCode) exit(exitCode); } //--- WRAPERS ---- HANDLE OpenProcess( DWORD processId ) { // Open the process for handle duplication return ::OpenProcess( PROCESS_DUP_HANDLE, TRUE, processId ); } HANDLE DuplicateHandle( HANDLE hProcess, HANDLE hRemote ) { HANDLE hDup = NULL; // Duplicate the remote handle for our process ::DuplicateHandle( hProcess, hRemote, GetCurrentProcess(), &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS ); return hDup; } //---------------------------------------------------------- ----- //API FUNCS bool EnableDebugPriv( void ) { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp; // enable the SeDebugPrivilege if ( ! OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) { //_tprintf( _T("OpenProcessToken() failed, Error = %d SeDebugPrivilege is not available.\n") , GetLastError() ); return false; } if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ) { //_tprintf( _T("LookupPrivilegeValue() failed, Error = %d SeDebugPrivilege is not available.\n"), GetLastError() ); CloseHandle( hToken ); return false; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) ) return false; //_tprintf( _T("AdjustTokenPrivileges() failed, Error = %d SeDebugPrivilege is not available.\n"), GetLastError() ); CloseHandle( hToken ); return true; } bool InitNativeFunctions() { NtQuerySystemInformation = (PNtQuerySystemInformation) GetProcAddress(GetModuleHandle ( L"ntdll.dll" ), (LPCSTR)"NtQuerySystemInform ation" ); NtQueryObject = (PNtQueryObject) GetProcAddress(GetModuleHandle ( L"ntdll.dll" ), (LPCSTR)"NtQueryObject"); NtQueryInformationFile = (PNtQueryInformationFile) GetProcAddress(GetModuleHandle ( L"ntdll.dll"), (LPCSTR)"NtQuery InformationFile" ); return NtQuerySystemInformation && NtQueryObject && NtQueryInformationFile; } WCHAR GetFileDevice(wchar_t* pName) { WCHAR fileName[MAX_PATH+3]; fileName[0] = L'\0'; wcsncat(fileName, L"C:", 2); wcsncat(fileName, pName, MAX_PATH); HANDLE h; int err; for (WCHAR actDrive = L'C'; actDrive <= L'D'; actDrive++ ) { fileName[0] = actDrive; h = CreateFile(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); err = GetLastError(); //32 Used by another process //3 The system cannot find the path specified switch (err) { case 3 : continue; case 32: return actDrive; } } return 0; } void GetFileNameThread( PVOID pParam ) { int len; GetFileNameThreadParam* p = (GetFileNameThreadParam*)pParam; p->rc = false; UCHAR lpBuffer[MAX_PATH*2]; PFILE_NAME_INFORMATION pFNI = (PFILE_NAME_INFORMATION)lpBuffer; DWORD iob[2]; DWORD ntRet = NtQueryInformationFile( p->hFile, iob, lpBuffer, MAX_PATH*2, 9 ); if ( ntRet == STATUS_SUCCESS){ len = pFNI->FileNameLength/2; if (len > MAX_PATH) len = MAX_PATH-1; wcsncpy(p->pName, pFNI->FileName, len ); p->pName [len] = L'\0'; p->rc = true; } } //Returns file name if handle h is file handle or FALSE if not. bool GetFileName (HANDLE h, PWCHAR pName, 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( processId ); if ( hRemoteProcess == NULL ) return FALSE; // Duplicate the handle handle = DuplicateHandle( hRemoteProcess, h ); } else handle = h; // Query the info size NtQueryObject( handle, 2, NULL, 0, &size ); lpBuffer = new UCHAR[size]; // Query the info size ( type = 2 = ObjectTypeInformation) if ( NtQueryObject( handle, 2, lpBuffer, size, NULL ) == 0 ) { int i = _wcsicmp (L"File", (wchar_t*)(lpBuffer+0x60)); if (i != 0) goto cleanup; GetFileNameThreadParam tp; tp.hFile = handle; tp.pName = pName; //Start the thread to get the file name HANDLE hThread = (HANDLE)_beginthread( GetFileNameThread, 0, &tp ); if ( hThread == NULL ) goto cleanup; if ( WaitForSingleObject(hThread, 50 ) == WAIT_TIMEOUT) { // Access denied, terminate the thread TerminateThread( hThread, 0 ); wcscpy(pName, L""); ret = false; } else ret = tp.rc; } cleanup: if ( remote ) { if ( hRemoteProcess != NULL ) CloseHandle( hRemoteProcess ); if ( handle != NULL ) CloseHandle( handle ); } if ( lpBuffer != NULL ) delete [] lpBuffer; return ret; } //---------------------------------------------------------- ----- PSYSTEM_HANDLE_INFORMATION Snapshot() { DWORD size = 0x2000; DWORD needed = 0; PSYSTEM_HANDLE_INFORMATION pHI; pHI = (PSYSTEM_HANDLE_INFORMATION) VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE ); if (! pHI) return NULL; // SYSTEM_INFORMATION_CLASS SystemHandleInformation <-- 16 if ( NtQuerySystemInformation( 16, pHI, size, &needed ) != 0 ) { if ( needed == 0 ) { VirtualFree( pHI, 0, MEM_RELEASE ); return NULL; } // The size was not enough VirtualFree( pHI, 0, MEM_RELEASE ); pHI = (PSYSTEM_HANDLE_INFORMATION) VirtualAlloc( NULL, size = needed + 256, MEM_COMMIT, PAGE_READWRITE ); } if ( pHI == NULL ) return NULL; // Query the objects ( system wide ) if ( NtQuerySystemInformation( 16, pHI, size, NULL ) != 0 ) { VirtualFree( pHI, 0, MEM_RELEASE ); return NULL; } return pHI; } bool GetProcessName(DWORD processID, wchar_t* name) { bool res; int k; HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID ); res = GetProcessImageFileName(hProcess, name, MAX_PATH) != 0; if (! res) k = GetLastError(); return res; } void PrintHandles(PSYSTEM_HANDLE_INFORMATION pHI) { wchar_t processName[MAX_PATH], fileName[MAX_PATH], tmp[MAX_PATH]; bool res; wchar_t driveLetter; if ( !pHI ) mmMsg(L"Snapshot failed", 3); int j=0; for (unsigned int i = 0; i < pHI->NumberOfHandles; i++ ) { SYSTEM_HANDLE_TABLE_ENTRY_INFO h = pHI->Handles; res = GetFileName((HANDLE)h.HandleValue, (wchar_t*)&fileName, h.UniqueProcessId); if (!res) continue; driveLetter = GetFileDevice(fileName); if ( driveLetter == 0 ) continue; res = GetProcessName(h.UniqueProcessId, tmp); if (res) GetFsFileName((wchar_t*)&tmp, (wchar_t*)&processName); if ( h.UniqueProcessId == 4 ) wcscpy(processName, L"System"); wprintf(L"NO:%i | %i\t\t H:%-5i PID:%i\n", i, j++, h.HandleValue, h.UniqueProcessId); wprintf(L"P : %s",processName ); &nbs p; &nbs p; wprintf(L"\n"); wprintf(L"FN: %c:%s", driveLetter, fileName ); &nbs p;wprintf(L"\n"); wprintf(L"----------------------------------\n"); } } int wmain(int argc, WCHAR* argv[]) { if (! EnableDebugPriv() ) ;mmMsg(L"debug failed\n", 1); if (! InitNativeFunctions() ) mmMsg(L"Import function failed\n", 2); PrintHandles ( Snapshot() ); wprintf(L"\n\n\nfinished"); return 0; }Sorry about all the random breaks, I copied a copied code.Here is the website I got it from, SysInternals Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ
LarryDalooza Posted April 16, 2008 Author Posted April 16, 2008 Thanks brother... yeah, I have that code and others ... I guess I am interested in "File Unlocking Gone Wild" experiences, where someone has deleted or corrupted system files. I would like to read any horror stories associated with unlocking files. Meanwhile I will google for stories. Lar. AutoIt has helped make me wealthy
James Posted April 16, 2008 Posted April 16, 2008 Are you not able to get the code working then? Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ
SkinnyWhiteGuy Posted April 16, 2008 Posted April 16, 2008 He can, and is very capable, of making it not only work, but giving it to us in AutoIt. What he's asking for is reasons/examples of why doing this might crash a computer, and if so, he would like to know before he gives us Weapons of Mass Destruction, AutoIt style.
James Posted April 16, 2008 Posted April 16, 2008 See, I thought he could do it, I just didn't understand why he was saying he has the code and others. This in AutoIt would rock, I guess the dangers of using it are the facts that system files can obviously be deleted, maybe a database of system files, so if you do accidentally delete it then it can be bought back?? Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ
Valik Posted April 16, 2008 Posted April 16, 2008 The major danger is applications becoming unstable and crashing. You take a handle and you close it outside the parameters of the program. Imagine you open a file and are writing to it and suddenly the handle is closed on you and you do not have any clue that it happened. This could crash the program. Now, if the program happens to be Explorer, then your whole shell is likely to go down. If the program were, say, Microsoft Word, then it's feasible that killing the entire application will kill all document windows leading to potential data-loss in those other windows. It's unlikely this will ever be included in AutoIt (built-in or UDF). It's too much of a hack and there's too much theoretical potential for introducing application instability. First it simulates being a debugger, which it is not, just to get access to the information. Then it uses system calls with bright scary warnings not to use them. Then it goes on to perform things outside the rules of conventional program flow. I'm not saying it's not useful, but I am saying it's not the kind of thing we need to be handing out like Halloween treats.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now