How does GetWindowText get the name of a window belonging to another process, without syscall to read this process memory?

I wanted to find out what the system calls from GetWindowText are. I wrote a simple program to call GetWindowText with a window handle in another process.

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MessageBox(0,"Attach debugger and set bp","on GetWindowTextA",0); HWND winmine = FindWindow(NULL,"Minesweeper"); if(winmine != NULL) { char buf[255] = ""; GetWindowTextA(winmine, buf, 254); MessageBox(0,buf,"Found",0); } else { MessageBox(0,"?","Found nothing",0); } return 0; } 

I connected the debugger and went through the GetWindowTextA call, manually stepping over everything except these API calls (in order):

  • GetWindowThreadProcessId (in GetWindowLong)
  • Interlockedincrement
  • WCSToMBEx (mostly WideCharToMultiByte)
  • InterlockedDecrement

None of these API calls seem to be able to read a line in memory that does not belong to the calling process. I used the usermode debugger, so of course I did not get into kernelmode without doing this. This means that GetWindowText got the window name without using the context switch. This, apparently, means that the text for each available window is available without a context switch .. and this may not be correct, because there is no way for Windows to save a copy of the text for each individual window / control in the system, on each single process.

I read this article . It mentions that the window names are stored in the quote “special place”, but do not explain how you can access this “special place” from another process without switching using syscall / context.

So, I am looking for an explanation as to how this is done. Any information you can provide is greatly appreciated.

+7
windows winapi system-calls
source share
2 answers

GetWindowText got the window name without performing a context switch. This, apparently, means that the text for each available window is available without a context switch.

This information is stored in memory that is shared by all processes using user32.dll . You can try to find the virtual space of your process for the unicode names of other process windows.

It is mapped to the process address space during user32.dll loading. There are some kernel structures / sections: win32k!gSharedInfo , win32k!ghSectionShared , win32k!gpsi and others (which I do not know about).

In fact, the lower 16 bits of the HWND represent the index into the index information array with the base address *(&user32!gSharedInfo + 1) . The first field of this window is the kernel address of another structure, which contains all the information about the general window. Subtracting the difference between the address of the kernel of the partition and its user space mapping (which is stored in TEB!Win32ClientInfo ), you can get the relevant information.

user32!ValidateHwnd is a function that converts a window handle to this address, which can be used by internal user32 functions such as user32!DefWindowProcWorker .

The GetWindowTextW pseudo- GetWindowTextW looks (except for error handling):

  GetWindowTextW(HWND hwnd, wchar_t* buf, int size) { inner_hwnd = ValidateHwnd(hwnd); if (TestWindowProcess(inner_hwnd)) SendMessageWorker(inner_hwnd, WM_GETTEXT, size, buf, FALSE); else DefWindowProcWorker(inner_hwnd, WM_GETTEXT, size, buf, FALSE); } 

DefWindowProcWorker , which is called in your case with WM_GETTEXT , will simply analyze the structure referenced by inner_hwnd and copy the window name to buf .


text for EDITTEXT controls doesn't seem to be saved this way

I never knew all the information that was stored there, although it seems like a good choice so as not to pollute the virtual process spaces with all types of user / gdi . In addition, lower integrity processes should not receive more important process integrity information.

+6
source share

because there is no way for Windows to keep a copy of the text for each individual window

The text certainly exists, and not as a copy. The text for the window is stored in the virtual memory of the process to which the window belongs. It may be in RAM, but not very likely if the process has been inactive for some time, specifically on disk in the swap file. This does not prevent GetWindowText () from making a copy. On the fly, when you call it.

GetWindowText () is limited, only documented to be able to copy the text of the window title, so it probably uses a bunch of desktop session to retrieve the text. Otherwise, this is a limitation for the winapi function, for example SendMessage (), you can use WM_GETTEXT to get a gigabyte from the Edit control. This certainly crosses the boundary of the process.

As a function of the operating system, SendMessage can, of course, violate all the rules that apply to ordinary processes. The OS has no problems accessing an arbitrary process virtual machine. Rules that usually break, your debugger does this as well. With functions you can use to also break rules, ReadProcessMemory () and WriteProcessMemory ().

+1
source share

All Articles