Log in

View Full Version : newbie user32, Windows question


DaBookshah
December 11th, 2006, 06:15
Obviously I haven't understood the windows system properly, because I have no idea how the picture is possible - the windowprocs list i mean.

http://www.users.tpg.com.au/adslm66g/pic.jpg (how the hell do you insert a picture?!?)

Just to show that I have tried to help myself first, my thoughts were:

The window proc is obviously invalid.....maybe some kind of windows message hook via Setwindowshookex? Nope, unless its been inlined somehow.

Ok, maybe messsages are never sent to the wndproc? Maybe in that peekmessage/dispatch message loop the messages are never actually sent to the wndproc? Nope, the messages are definetly sent.

Can someone please enlighten me.

disavowed
December 11th, 2006, 11:31
My guess is that it's a topmost window from another program. See the HWND_TOPMOST description at http://msdn2.microsoft.com/en-us/library/ms633545.aspx

Maximus
December 11th, 2006, 12:38
Quote:

As part of the Vista re-architecture, all services were moved off the interactive desktop into Session 0. hwnd and window manager operations are only effective inside a session and cross-session attempts to manipulate the hwnd will fail.


Is this the m$ workaround for avoiding user's escalation with interactive desktop assigned by default to services?

blabberer
December 11th, 2006, 13:21
if you are talking about winproc and classproc not in userland memory that has been like that from i dont know i saw them long long back
you open any subclassed exes like calc.exe winmine.exe and such

they all have thier wndprocs and classprocs in unaccessible memory

they all use gdientry13 etc and use int2b to come back to user land when pertinent messages are recieved

Code:

0007FE10 0007FEE8 \pMsg = WM_COMMAND hw = A0256 ("Calculator" Notify = MENU/BN_CLICKED... ID = 300. hControl = NULL



see pic below

DaBookshah
December 11th, 2006, 20:20
Thanks for the replies disavowed and blabberer........but I'm still lost . Can you explain that bit about int 2b and gdientry a bit more blabberer? Where in userland code does execution return to when a "pertinent message" is recieved?

Basically I want to find out where the wndproc is, if possible.

Thanks

LLXX
December 12th, 2006, 00:08
You'll need a ring-0 debugger to go there.

Don't try following it with something like OllyDbg.

disavowed
December 12th, 2006, 02:22
Quote:
[Originally Posted by Maximus;63038]Is this the m$ workaround for avoiding user's escalation with interactive desktop assigned by default to services?

It's a solution. Why do you refer to it as a "workaround"? What would you have recommended instead?

blabberer
December 12th, 2006, 13:53
Quote:

Thanks for the replies disavowed and blabberer........but I'm still lost . Can you explain that bit about int 2b and gdientry a bit more blabberer? Where in userland code does execution return to when a "pertinent message" is recieved?


oops you are asking some tough question

i dont know how much you can follow i cant explain well i talk incoherantly like my nick so its your luck how much you would understand from the gibberish that's following below (and this is not perse written with iron clad guarentee that everything i write below is correct there maybe lapses inconsistencies utterly wrong statements and all the things that can go wrong so you are forewarned )

so since save my skin eula is over lets get to subject

once upon a time long long ago there was some primitive operating system
which allowed access to every piece of memory that it could access
so when some thing went wrong (bug , intentional or not) that took down the entire operating system along with it

now some one wanted to stop this so they divided memory into two parts
and assigned one part of it to your daily normal run of the mill applications
and assigned another part of it to core operating system

the part that was assigned to core operating system was loosely termed ring 0 (also called as kernel land)

the part that was assigned to normal application were termed ring 3 also called as userland

now these two cant coexist without talking to each other

here comes the stubs which transfer all the routines from userland after validating them to some extent (there may be instances where validation itself isnt valid and things can go awry but that not the point here )

these stubs are called system calls (in processors where fast syscalls werent availble interrupts were used one of the interrupts is the famous
int 2e

Code:

lkd> !idt 2e
Dumping IDT:
2e: 804deea6 nt!KiSystemService


in processors where fast syscalls were available these were called via sysenter
sysenter again is another stub which exists in a shared user page
called _KUSER_SHARED_PAGE

Code:

7FFE0300 7C90EB8B ntdll.KiFastSystemCall
7FFE0304 7C90EB94 ntdll.KiFastSystemCallRet

7C90EBA5 ntdll.KiIntSystemCall 8D5424 08 LEA EDX, DWORD PTR SS:[ESP+8]
7C90EBA9 CD 2E INT 2E


7C90EB8B ntdll.KiFastSystemCall 8BD4 MOV EDX, ESP
7C90EB8D 0F34 SYSENTER


all this syscall does is save all the arguments and save a return pointer (cs:eip in case of int routines or pointer to esp on stack and enter system (or ring 0 or kernel land however it is called)

now system checks if this call originated from user land or kernel land
if it finds that this call originated from user land it again performs some strict validation (holes may exist and thats not the point here)
if it finds all is well performs the requested action and return back to user land

see a sample of call stack here where it returns to user land after processing
some message

Code:

Call stack of main thread
Address Stack Procedure / arguments Called from Frame
0007FADC 77D484BC Includes ntdll.KiFastSystemCallRet USER32.NtUserValidateHandleS 0007FAFC
0007FAE0 77D48564 USER32.NtUserValidateHandleSecure USER32.HMValidateHandle+8F 0007FAFC
0007FB00 77D4BA07 USER32.ValidateHwnd USER32.77D4BA02 0007FAFC
0007FB0C 5AD8DBB4 USER32.MapWindowPoints UxTheme.5AD8DBAE 0007FB08
0007FB10 0005028C hWndFrom = 0005028C ('F-E',class='Button',parent=000E026C)
0007FB14 000E026C hWndTo = 000E026C ('Calculator',class='SciCalc')
0007FB18 0007FB2C pPoints = 0007FB2C
0007FB1C 00000002 nPoints = 2
0007FB64 773D6945 ? UxTheme.DrawThemeParentBackground comctl32.773D693F 0007FB60
0007FB78 773F8868 ? comctl32.773D6930 comctl32.773F8863 0007FB74
0007FBF0 773F8DC7 comctl32.773F87BA comctl32.773F8DC2 0007FBEC
0007FC80 77D48709 Includes comctl32.773F8DC7 USER32.InternalCallWinProc+2 0007FC7C
0007FCAC 77D487EB USER32.InternalCallWinProc USER32.UserCallWinProcCheckW 0007FCA8
0007FCB0 773F8B56 Arg1 = 773F8B56
0007FCB4 0005028C Arg2 = 0005028C
0007FCB8 0000000F Arg3 = 0000000F
0007FCBC 00000000 Arg4 = 00000000
0007FCC0 00000000 Arg5 = 00000000
0007FD14 77D4B368 ? USER32.UserCallWinProcCheckWow USER32.DispatchClientMessage 0007FD10
0007FD18 00000000 Arg1 = 00000000
0007FD1C 773F8B56 Arg2 = 773F8B56
0007FD20 0005028C Arg3 = 0005028C
0007FD24 0000000F Arg4 = 0000000F
0007FD28 00000000 Arg5 = 00000000
0007FD2C 00000000 Arg6 = 00000000
0007FD30 005AF564 Arg7 = 005AF564
0007FD34 00000001 Arg8 = 00000001


i dont know if you followed upto here and still survived

if you survived read on

int2e calls are stubs to calls in nt (ntoskrnl.exe)

now many of the graphical user interface (gui) is handled by win2k.sys

see a setbackgrond color opration call stack from gdi

Code:

Call stack of main thread
Address Stack Procedure / arguments Called from Frame
0007F908 77D4CB20 GDI32.SetBkColor USER32.77D4CB1A 0007F940
0007F90C 98010B94 hDC = 98010B94
0007F910 00D8E9EC Color = RGB(236.,233.,216.)
0007F944 77D4B2A1 USER32.RealDefWindowProcWorker USER32.RealDefWindowProcW+22 0007F940
0007F948 000E026C Arg1 = 000E026C
0007F94C 00000135 Arg2 = 00000135
0007F950 98010B94 Arg3 = 98010B94
0007F954 0005028C Arg4 = 0005028C
0007F958 00000000 Arg5 = 00000000
0007F960 5AD71AF6 USER32.RealDefWindowProcW UxTheme.5AD71AF3 0007F95C
0007F964 000E026C Arg1 = 000E026C
0007F968 00000135 Arg2 = 00000135
0007F96C 98010B94 Arg3 = 98010B94
0007F970 0005028C Arg4 = 0005028C
0007F9B8 5AD71B3D UxTheme.5AD719C4 UxTheme.5AD71B38 0007F9B4
0007F9D4 77D4B9BD UxTheme.5AD71B25 USER32.77D4B9B7 0007F9D0
0007FA1C 010063FB ? USER32.DefWindowProcW calc.010063F5 0007FA18
0007FA20 000E026C hWnd = 000E026C ('Calculator',class='SciCalc')
0007FA24 00000135 Message = WM_CTLCOLORBTN
0007FA28 98010B94 hDC = 98010B94
0007FA2C 0005028C hWnd = 0005028C ('F-E',class='Button',parent=000E026C)
0007FA50 77D48709 Maybe calc.01006118 USER32.InternalCallWinProc+2 0007FA4C
0007FA54 000E026C hWnd = 000E026C ('Calculator',class='SciCalc')
0007FA58 00000135 Message = WM_CTLCOLORBTN
0007FA5C 98010B94 hDC = 98010B94
0007FA60 0005028C hWnd = 0005028C ('F-E',class='Button',parent=000E026C)
0007FA7C 77D487EB USER32.InternalCallWinProc USER32.UserCallWinProcCheckW 0007FA78
0007FA80 01006118 Arg1 = 01006118
0007FA84 000E026C Arg2 = 000E026C
0007FA88 00000135 Arg3 = 00000135
0007FA8C 98010B94 Arg4 = 98010B94
0007FA90 0005028C Arg5 = 0005028C
0007FAE4 77D4B743 ? USER32.UserCallWinProcCheckWow USER32.77D4B73E 0007FAE0
0007FAE8 00000000 Arg1 = 00000000
0007FAEC 01006118 Arg2 = 01006118
0007FAF0 000E026C Arg3 = 000E026C
0007FAF4 00000135 Arg4 = 00000135
0007FAF8 98010B94 Arg5 = 98010B94
0007FAFC 0005028C Arg6 = 0005028C
0007FB00 0058A56C Arg7 = 0058A56C
0007FB04 00000001 Arg8 = 00000001
0007FB20 77D4B7AB USER32.SendMessageWorker USER32.SendMessageW+44 0007FB1C
0007FB40 773F6C9C USER32.SendMessageW comctl32.773F6C96 0007FB3C
0007FB44 000E026C hWnd = E026C
0007FB48 00000135 Message = WM_CTLCOLORBTN
0007FB4C 98010B94 hDC = 98010B94
0007FB50 0005028C hWnd = 0005028C ('F-E',class='Button',parent=000E026C)
0007FB78 773F887B comctl32.773F6C35 comctl32.773F8876 0007FB74
0007FB7C 50000000 Arg1 = 50000000
0007FB80 98010B94 Arg2 = 98010B94
0007FBF0 773F8DC7 comctl32.773F87BA comctl32.773F8DC2 0007FBEC
0007FC80 77D48709 Includes comctl32.773F8DC7 USER32.InternalCallWinProc+2 0007FC7C
0007FCAC 77D487EB USER32.InternalCallWinProc USER32.UserCallWinProcCheckW 0007FCA8
0007FCB0 773F8B56 Arg1 = 773F8B56
0007FCB4 0005028C Arg2 = 0005028C
0007FCB8 0000000F Arg3 = 0000000F
0007FCBC 00000000 Arg4 = 00000000
0007FCC0 00000000 Arg5 = 00000000
0007FD14 77D4B368 ? USER32.UserCallWinProcCheckWow USER32.DispatchClientMessage 0007FD10
0007FD18 00000000 Arg1 = 00000000
0007FD1C 773F8B56 Arg2 = 773F8B56
0007FD20 0005028C Arg3 = 0005028C
0007FD24 0000000F Arg4 = 0000000F
0007FD28 00000000 Arg5 = 00000000
0007FD2C 00000000 Arg6 = 00000000
0007FD30 005AF564 Arg7 = 005AF564
0007FD34 00000001 Arg8 = 00000001



so in one of the calls in gdi like below if you trace enough you will find
sysenter is being invoked like in call below
Code:

Call stack of main thread
Address Stack Procedure / arguments Called from Frame
0007F740 77D506D0 GDI32.IntersectClipRect USER32.DrawTextExWorker+0D1 0007F7E0
0007F744 98010B94 hDC = 98010B94
0007F748 00000000 Left = 0
0007F74C 00000000 Top = 0
0007F750 00000024 Right = 24 (36.)
0007F754 0000001D Bottom = 1D (29.)
0007F7E4 77D505F0 ? USER32.DrawTextExWorker USER32.DrawTextExW+19
0007F808 77D4FFB7 USER32.DrawTextExW USER32.77D4FFB2 0007F804
0007F80C 98010B94 hDC = 98010B94
0007F810 000A7632 Text = "F-E"
0007F814 FFFFFFFF Count = FFFFFFFF (-1.)
0007F818 0007FA7C pRect = 0007FA7C {0.,0.,36.,29.}
0007F81C 00000025 Flags = DT_CENTER|DT_VCENTER|DT_SINGLELINE
0007F820 00000000 pDrawTextParams = NULL
0007F83C 010061F7 USER32.DrawTextW calc.010061F1 0007F838
0007F840 98010B94 hDC = 98010B94
0007F844 000A7632 Text = "F-E"
0007F848 FFFFFFFF Count = FFFFFFFF (-1.)
0007F84C 0007FA7C pRect = 0007FA7C {0.,0.,36.,29.}
0007F850 00000025 Flags = DT_CENTER|DT_VCENTER|DT_SINGLELINE


Code:

77F16899 GDI32.IntersectClipRe> $ 8BFF MOV EDI, EDI
cut offff------------------------
77F168C0 |. 56 PUSH ESI
77F168C1 |. E8 0A000000 CALL NtGdiIntersectClipRect <-------
77F168C6 |> 5E POP ESI ; USER32.77D48684
77F168C7 |. 5D POP EBP ; USER32.77D48684
77F168C8 \. C2 1400 RETN 14

the actual call NtGdiIntersectClipRect is

77F168D0 GDI32.NtGdiIntersectClipRect /$ B8 DE100000 MOV EAX, 10DE
77F168D5 |. BA 0003FE7F MOV EDX, 7FFE0300
77F168DA |. FF12 CALL NEAR DWORD PTR DS:[EDX]
77F168DC \. C2 1400 RETN 14



as you can see its just a stub call dword ptr ds:[edx]

now how does system know wtf arrived and who left

thats where the mov eax comes into play

there are unique identifiers to every system call

1 to 127 or some thing more is allocated to nt
and anything above 1000 is allocated to win2k.sys

and all system needs to know to execute any request is to have a valid identifier and a user stack pointer in register edx

its either life or death result from there on if the identifier is valid
and the internal validation in kernel checks out you get what you requested
else you get back a cryptic NT_STATUS ( 0x12345678 DATA_TYPE_MISALIGNED)


now how do you find some winproc if all else is so deep hidden

not easy if you are just interested in some serial on some dumb app

but if you are interested in diving down and getting your hands dirty on the system internals
finding anything is a piece of cake

you have to start from tracing from the first level of validation

so that would be user32.dll which almost always ends up in ntdll.dll either via
kernel32.dll or directly

if you have the pdbs which ms offers from thier symbol servers the task could be little easier

for example there is a call in user32.dll that always lies in the path of any
winproc and it is aptly named
Code:

77D486E1 USER32.InternalCallWinProc /$ 55 PUSH EBP

it takes 5 arguments and its first argument is always
the winproc
Code:

0007F66C 77D487EB /CALL to Assumed StdFunc5 from USER32.77D487E6
0007F670 01006118 |Arg1 = 01006118
0007F674 001A028E |Arg2 = 001A028E
0007F678 00000024 |Arg3 = 00000024
0007F67C 00000000 |Arg4 = 00000000
0007F680 0007F768 \Arg5 = 0007F768



so to enumerate i set a message break point to stop on WM_COMMAND on calc.exe here are the results

Code:

Log data
Address Message
77D486E1 Breakpoint at USER32.InternalCallWinProc
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = EN_UPDATE... ID = 403.
hControl = 0017026E (class='Edit',parent=001A028E)
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = EN_CHANGE... ID = 403.
hControl = 0017026E (class='Edit',parent=001A028E)
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = EN_SETFOCUS... ID = 403.
hControl = 0017026E (class='Edit',parent=001A028E)
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = EN_KILLFOCUS... ID = 403.
hControl = 0017026E (class='Edit',parent=001A028E)
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = MENU/BN_CLICKED... ID = 133.
hControl = 000502B6 ('9',class='Button',parent=001A028E)
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = EN_UPDATE... ID = 403.
hControl = 0017026E (class='Edit',parent=001A028E)
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = EN_CHANGE... ID = 403.
hControl = 0017026E (class='Edit',parent=001A028E)
7C810856 New thread with ID 000006C4 created
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = EN_SETFOCUS... ID = 403.
hControl = 0017026E (class='Edit',parent=001A028E)
01006118 CALL to Assumed WinProc from USER32.77D48706
hWnd = 001A028E ('Calculator',class='SciCalc')
Message = WM_COMMAND
Notify = EN_KILLFOCUS... ID = 403.
hControl = 0017026E (class='Edit',parent=001A028E)


are you still awake ?

hope i didnt bore you to death

Maximus
December 13th, 2006, 05:41
mmh... nice and good explanation, blabberer. Last time I tried to explain this stuff I ended up explaining descriptor's evolution from 286 on
...I wish to suggest the guy to buy "Subverting the Windows Kernel" book at amazon (they'd have it used too). Well spent money, IMHO.

@disavowed: you are right, it's indeed the solution to the problem.

DaBookshah
December 22nd, 2006, 21:54
Awsome, thanks.