win32k.sys
not without cost, so the first thing to do is to look at the win32k!tagSHAREDINFO
, which is answered by the symbol win32k!gSharedInfo
, and also on the data type HWND
, which is very closely associated with it.gSharedInfo
stores pointers to various window-related structures and, best of all, many of these structures are mapped into user space (put into the user-mode, in our opinion), and the corresponding user32!gSharedInfo
symbol has user32!gSharedInfo
for some time (or whist, either from the seven) became exported.aheList
- points to an array of win32k!_HANDLEENTRY
type elements win32k!_HANDLEENTRY
;HeEntrySize
- contains the size of the win32k!_HANDLEENTRY
.HWND
window handle are in fact the index in the gSharedInfo->aheList
. For example, if we have a window
variable that contains the HWND
handle:wUniq
field of the win32k!_HANDLEENTRY
contains the top 16 bits of the HWND
descriptor and, apparently, serves the simple purpose of separating objects that occupy the same address in a given array at different time intervals. Thus, if an object is freed and later its place is taken, for example, by a new window with wUniq = 0x12
, then according to the old descriptor 0x0011024c
it will be impossible to access it.bFlags
and bType
contain various flags and the type of object addressed by the phead field, respectively. In more detail possible values accepted by them can be looked in ReactOS .bType
value bType
:TYPE_WINDOW = 1
phead
field addresses the win32k!tagWND
.user32!gSharedInfo->aheList[…].phead
stores the address belonging to the kernel. However, if you wish, you can get the address of its user mapping, but this is another story, so for details I refer you to the HWND
window handle and the user32!ValidateHWND
procedure that returns the tagWND*
, or rather to the user32!HMValidateHandle
.pOwner
field of the win32k!_HANDLEENTRY
pOwner
structure not considered earlier contains a pointer to win32k!_W32THREAD
stream to which the object belongs. Each thread stores this pointer in win32k!_KTHREAD->Win32Thread
(why not in _ETHREAD
), and also, which is much more important in our case, in TEB!Win32ThreadInfo
.user32!gSharedInfo->aheList[…]
, which:bType == TYPE_WINDOW
;pOwner == TEB!Win32ThreadInfo
.wUniq
16 bits of the descriptor, and the upper 16 bits will be contained in the wUniq
field.user32!FindWindow
? At the moment when we need it, neither the name nor the class will be filled in by the window.PEB!KernelCallbackTable
.kernel
, but received their name because their client is usually win32k.sys
, accessing them when it is necessary to perform an operation in the user space. The call is made via ntdll!KiUserCallbackDispatcher
similar to exception scheduling .nt!KeUserModeCallback
. The call is made on the kollbek index. Address resolving by index is done already in ntdll!KiUserCallbackDispatcher
.user32!SetWindowLongPtr
, and in fact - its execution in the form of win32k!xxxSetWindowData
. We confine ourselves to only one case of interest - with the GWLP_WNDPROC
parameter.win32k!xxxSetWindowData
first performs various checks. For example, is the window owned by the process whose thread is trying to set the WndProc
, and also whether this window is already destroyed ( FNID_DELETED_BIT
bit).WndProc
parameter ( value_
in the screenshot), MapClientToServerPfn
is MapClientToServerPfn
. This simple and extremely useful function maps functions from win32k!gpsi->apfnClientW
and win32k!gpsi->apfnClientA
to the corresponding functions from win32k!gpsi-> aStoCidPfn
:WndProc
possible, then the procedure call can be optimized by referring directly to the implementation of the function in the kernel, for example, win32k!xxxDefWindowProc
, without wasting time switching to user mode to call the wrapper, for example, ntdll!NtdllDefWindowProc_A
, which user32!DefWindowProcA
is an end-to-end export.WFSERVERSIDEPROC
flag is raised at the window, after which the mapped value is entered in its win32k!tagWND->lpfnWndProc
.user32!SetWindowLongPtr
, then the corresponding procedure from win32k.sys
in kernel mode will actually be executed.win32k!xxxCreateWindowEx
procedure is fully responsible for win32k!xxxCreateWindowEx
. First, by calling win32k!HMAllocObject
tagWND object is tagWND
and information about it is entered into the gSharedInfo->aheList
:hex-rays
takes a couple of thousand lines, so there is no point or opportunity to dwell on all the actions performed.SetWindowLongPtr(hwnd, GWLP_WNDPROC, DefWindowProc)
on the window at the moment when it is already created, but it still has the lpfnWndProc
field. After all, this field is filled from the class field, in which it is probably already stored mapped by MapClientToServerPfn
, if such mapping is possible.SetWindowLongPtr
to raise the WFSERVERSIDEPROC
flag before the WndProc
address is filled with the value from the class field. At the same time, this flag is not reset when the WndProc
field is set, as the developers did not anticipate the possibility that it can be installed. There is only the logic of setting the flag for the window, if the corresponding class flag is raised.SetWindowLongPtr
at run time CreateWindowEx
negligible, because you must first find the HWND
windows in the user32!gSharedInfo->aheList
, then the user32!SetWindowLongPtr -> … -> win32k!xxxSetWindowData
chain user32!SetWindowLongPtr -> … -> win32k!xxxSetWindowData
should work out the call chain what happens initialization of the tagWND
fields in win32k!xxxCreateWindowEx
. You can, of course, play with processor affinity
and thread priorities. However, for Windows 7 and earlier versions, there is a simple way.win32k!xxxCreateWindowEx
, all the information we are interested in fits into several hex-rays lines:hIcon
icon, but was not specified for the small hIconSm
icon, then win32k!xxxCreateWindowEx
copies the window, or rather, scales it, the window for filling the win32k!tagCLS->spicnSm
field win32k!tagCLS->spicnSm
. This action is performed by the win32k!xxxCreateClassSmIcon
, which delegates the task to one of the above-described user so-called kernel callbacks
:user32!_ClientCopyImage
. He performs the task.win32k!xxxCreateWindowEx
, the WndProc
window is immediately filled from the WndProc
class. Then, apparently, if the WFSERVERSIDEPROC
flag WFSERVERSIDEPROC
raised in the class, it is also raised for the window.user32!_ClientCopyImage
:SetWindowLongPtr
for the newly created window:SetWindowLongPtr
, which raises the bServerSideWindowProc
flag in the appropriate window structure.win32k!xxxCreateWindowEx
overwrites lpfnWndProc
value from the class field.win32k!xxxCreateWindowEx
installation of tagWND->lpfnWndProc
and the call to win32k!xxxCreateClassSmIcon
are in reverse order compared to earlier versions. Thus, the user32!_ClientCopyImage
hook user32!_ClientCopyImage
will not help.Source: https://habr.com/ru/post/257879/
All Articles