Is it possible? It doesn't work with DestroyWindow (Access Denied).
Is it possible? It doesn't work with DestroyWindow (Access Denied).
"The Internet treats censorship as damage and routes around it." - John Gilmore
It's not a very nice thing to do.
Well..you can try closing its instance.
* PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
* Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.
It's possible that your app may not have sufficient security privileges to kill the window as indicated by the Access denied message. You could set the privilege level of your app to SeDebugPrivilege which will allow you to kill anything including system processes. Check out TOKEN_PRIVILEGES, OpenProcessToken, LookupPrivilegeValue and AdjustTokenPrivileges.
Last edited by BobS0327; 01-01-2007 at 07:16 PM.
It is possible, you might have to do some trickery to emulate the functionality of destroywindow, or make it think you are calling it from the remote window's thread.Originally Posted by http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/destroywindow.asp
Just an addendum. SeDebugPrivilege does not work. I tried it in a demo app and I still get an access denied message.
I tried SeDebugPrivilege too. Also sending WM_CLOSE and WM_DESTROY messages...
"The Internet treats censorship as damage and routes around it." - John Gilmore
If you're sending WM_CLOSE you obviously have a window handle. The catch is that getting a handle of a window, or sending messages to it, also require privileges (particularly if you don't own the window). Applications can also choose to ignore WM_CLOSE. You can also try posting a WM_QUIT message to that window which, for most windows applications, will cause the windows event loop to be terminated (assuming, of course, you have sufficient privileges to send the message to that window).
I wonder if SetParent() helps...
"The Internet treats censorship as damage and routes around it." - John Gilmore
The 'window parent' has nothing to do with thread ownership. This is an interesting problem and it would seem as though Windows makes this intentionally difficult. It seems that it would be extremely hard to emulate DestroyWindow's functionality in a remote setting, but I had the funny idea that you could hook some function that you know is being called that you could snatch a window handle from (for example, BeginPaint or something), and then DestroyWindow the handle you get. Mwahahahahaha. Oh yeah, that's if throwing the messages at the window like grumpy suggested doesn't work.
How about this?Code:SetWindowLong(window,GWL_HINSTANCE,(LONG)GetModuleHandle(NULL));
"The Internet treats censorship as damage and routes around it." - John Gilmore
No.
A) Microsoft Windows XP and earlier: The SetWindowLongPtr function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.
B) What did you think setting the app's HINSTANCE is going to do? I don't know what it would do. I wouldn't think it would do anything. It's not like it would rebase the app or anything, much less do anything to help the the remote window closing sitch.
Face it, the only reliable way you're going to do this is by injecting a DLL that takes over a function like CreateWindowEx (or something else that uses a window handle) and go from there. You'll be in the same process so you can do what you like.
I tried using the dll inject approach with the following code but I still get an access denied.
Code://File dllmain.cpp // Compile cl.exe /LD dllmain.cpp #pragma comment(lib, "user32.lib") #include <windows.h> BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { HWND hWnd; LPVOID lpMsgBuf; hWnd = FindWindow("MyWindow", NULL); if(hWnd != NULL) { MessageBox(NULL,"Window found!!!, now destroy it", "FOUND" ,MB_OK); DestroyWindow(hWnd); } FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL ); MessageBox(NULL, (LPCSTR)lpMsgBuf, "GetLastError", MB_OK); LocalFree(lpMsgBuf); return TRUE; }Code://File: inject.cpp // Compile cl.exe inject.cpp #pragma comment(lib, "advapi32.lib") #pragma comment(lib, "user32.lib") #include <windows.h> #include <stdio.h> #include <tlhelp32.h> #include <shlwapi.h> #define PROCESS_NAME "win.exe" #define DLL_NAME "Dllmain.dll" #define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ) unsigned long GetTargetProcessIdFromProcname(char *procName) { PROCESSENTRY32 pe; HANDLE thSnapshot; BOOL retval, ProcFound = false; thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(thSnapshot == INVALID_HANDLE_VALUE) { MessageBox(NULL, "Cannot create create toolhelp snapshot", "Toolhelp Snapshot", NULL); return false; } pe.dwSize = sizeof(PROCESSENTRY32); retval = Process32First(thSnapshot, &pe); while(retval) { if(stricmp( pe.szExeFile, procName) == 0) { ProcFound = true; break; } retval = Process32Next(thSnapshot,&pe); pe.dwSize = sizeof(PROCESSENTRY32); } return pe.th32ProcessID; } BOOL InjectDLL(DWORD ProcessID, char *dllName) { HANDLE Proc; char buffer[50]={0}; LPVOID RemoteString, LoadLibAdd; if(!ProcessID) return false; Proc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, ProcessID); if(!Proc) { sprintf(buffer, "OpenProcess() failed: %d", GetLastError()); MessageBox(NULL, buffer, "InjectDLL", NULL); return false; } LoadLibAdd = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(Proc, (LPVOID)RemoteString, dllName, strlen(dllName), NULL); CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAdd, (LPVOID)RemoteString, NULL, NULL); CloseHandle(Proc); return true; } BOOL LoadDll(char *procName, char *dllName) { char buf[128] = {0}; DWORD ProcID = 0; ProcID = GetTargetProcessIdFromProcname(procName); if(ProcID == false) return false; if(!(InjectDLL(ProcID, dllName))) { MessageBox(NULL, "Process located, but injection failed", "LoadDLL", NULL); return false; } else return true; } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { if(LoadDll(PROCESS_NAME, DLL_NAME) == false) printf("LoadDLL failed\n"); return 0; }
Err okay then, disassemble the target, pop in a DestroyWindow() and reassemble. Voilá.
What I meant was to inject a DLL and overwrite the address of an existing linked function, like CreateWindowEx(). That way, the thread creating the window will call into your code and you can be that thread. Of course, that reduces flexibility in that you need to take a function and hope that it's called when you want. Otherwise you're at the mercy of the target.
Last edited by SMurf; 01-02-2007 at 12:52 PM.