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