PDA

View Full Version : Window creation woes


tdennist
November 10th, 2008, 12:55
Hi,

I'm trying to eliminate a nag screen. It appears once upon opening the application, and then not again. However, I believe I'm being led astray by a non-standard method of window creation.

The program is written in VC++ 6.0, and I've determined via ResourceHacker that the dialog (nag screen) in question is not pre-built.

I've set breakpoints on all (three) calls to CreateWindowExA and watched the lpClassName change in Olly to see if I could catch when the nag screen class shows up. It does not. I know the class name via View->Windows in Olly.

I then set a message bp on the ClassProc of the nag screen for window creation and destruction. The message that breaks when I destroy the nag screen:

Stack snapshot:
Code:

0012F644 7E418734 /CALL to Assumed WinProc from USER32.7E418731
0012F648 007A03B8 |hWnd = 007A03B8 ('UNREGISTERED COPY',class='#32770',parent=042C01F6)
0012F64C 00000002 |Message = WM_DESTROY
0012F650 00000000 |wParam = 0
0012F654 00000000 \lParam = 0

(note the class name '#32770' -- that's the nag screen class name. Is this information identifying for the application in any way? If so, I will promptly remove it and replace it with something more generic)

BP (in module USER32):
Code:

7E43E577 U> 8BFF MOV EDI,EDI
7E43E579 55 PUSH EBP
7E43E57A 8BEC MOV EBP,ESP
7E43E57C 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8] ; USER32.DefDlgProcA
7E43E57F E8 5C9FFDFF CALL USER32.7E4184E0

I don't know if this is any use to me.

Next I set breakpoints on DefWindowProcA calls in the module and watch the hWnd value in Olly until my class name shows up. Sure enough it does this time, only never with a WM_CREATE but with a WM_WINDOWPOSCHANGING. The class name shows up several times with different hWnd values here, always with the same message. Upon completion of the last one, the entire application shows up, along with the nag screen on top of it. So I view the call tree from that DefWindowProcA call and get a call from the main app module. That call looks like:

Code:

004DF3A7 . FF7424 0C PUSH DWORD PTR SS:[ESP+C] ; /Arg1 = 0012F1E8
004DF3AB . 8BC7 MOV EAX,EDI ; |
004DF3AD . 80E4 F0 AND AH,0F0 ; |
004DF3B0 . 8946 64 MOV DWORD PTR DS:[ESI+64],EAX ; |
004DF3B3 . E8 3AD5FFFF CALL appname.004DC8F2 ; \appname.004DC8F2

With the obvious identifying information removed.

My question is...what steps can I take next? I'm not sure how to simply "skip" a call to nag creation if one generic method is used to create/display the window (am I correct about that?) and I can't simply remove the resource because it's created at run-time.

I don't know if I've included enough information in this post to receive help, or if I've posted more than is needed, or if the snippets I posted are the appropriate ones. At any rate, I appreciate any help or pointers passed my way.

If nothing else, the underlying question in all of this is: do I have a legitimate approach? Or, if I don't, what are some key terms or phrases I can use to research in the correct direction?

Thanks!

PS: the nag screen's parent window is of class 'Afx:400000:8:10011:0:1f60463'. What is that?

reverser
November 10th, 2008, 19:32
#32770 is the class name for dialogs. Check for the CreateDialog* functions. Afx was the original name of the MFC framework, so your program is using MFC. Such names are created by AfxRegisterWndClass().

blabberer
November 11th, 2008, 14:22
#32770 is a system class for DialogBox iirc you might find this link posted here for similar question earlier if you searched
because ms is notorious for scrapping urls regularly
ill post it again

http://msdn.microsoft.com/en-us/library/ms633574(VS.85).aspx

Code:

The following table describes the system classes that are available only for use by the system. They are listed here for completeness sake.

Class Description
ComboLBox The class for the list box contained in a combo box.
DDEMLEvent Windows NT/Windows 2000/Windows XP: The class for Dynamic Data Exchange Management Library (DDEML) events.
Message Windows 2000/Windows XP: The class for a message-only window.
#32768 The class for a menu.
#32769 The class for the desktop window.
#32770 The class for a dialog box.
#32771 The class for the task switch window.
#32772 Windows NT/Windows 2000/Windows XP: The class for icon titles.



DefDialogProc is a handler that handles unhandled messages by the DialogProc you wont find anything usefull in that call

Code:

its like
if WM_COMMAND() \\ some command that's usefull for me so i handle
{
Do this
}
else if WM_USER+$@# \\ MyDefFor Registering Crap
{
DoRegister()
}
Else
DefDialogProc() \\ nothing usefull just send it back to system via laundry


most of the mfc things are subclassed
so you have to find where the subclassed or superclassed DialogProcExists
(look for switches , switch bases when you meet defdlgproc , find the jump paths )

and you will find the real call or comaparison

tdennist
November 12th, 2008, 20:51
Well. This so far has been turned out to be far more complex than I had originally anticipated. I decided to abandon the tactic of setting breakpoints on intermodular calls like CreateDialog, Window, etc. Instead, I stepped through the program until the nag popped up, set a breakpoint, restarted the app, stepped into the call, rinse and repeat. I believe this to be a more legitimate technique for this purpose, anyhow.

So, by doing that I've narrowed down more precisely in the application where the nag dialog is being created. The only problem is...there's nothing remotely similar to "CreateDialog" or Window or ShowWindow or anything really at all related to windows or dialogs.

Code:

004D1DA8 |> 8B06 |/MOV EAX,DWORD PTR DS:[ESI] ; appname.004FE4B0
004D1DAA |. |8BCE ||MOV ECX,ESI ; appname.005307D8
004D1DAC |. |FF50 5C ||CALL DWORD PTR DS:[EAX+5C] ; Drawing window components
004D1DAF |. |85C0 ||TEST EAX,EAX ; appname.004FE4B0
004D1DB1 |. |74 27 ||JE SHORT appname.004D1DDA
004D1DB3 |. |8B06 ||MOV EAX,DWORD PTR DS:[ESI] ; appname.004FE4B0
004D1DB5 |. |8D6E 30 ||LEA EBP,DWORD PTR DS:[ESI+30]
004D1DB8 |. |55 ||PUSH EBP
004D1DB9 |. |8BCE ||MOV ECX,ESI ; appname.005307D8
004D1DBB |. |FF50 64 ||CALL DWORD PTR DS:[EAX+64] ; appname.004D1DE7
004D1DBE |. |85C0 ||TEST EAX,EAX ; appname.004FE4B0
004D1DC0 |. |74 07 ||JE SHORT appname.004D1DC9
004D1DC2 |. |6A 01 ||PUSH 1
004D1DC4 |. |895C24 14 ||MOV DWORD PTR SS:[ESP+14],EBX
004D1DC8 |. |5F ||POP EDI ; appname.004D17B5
004D1DC9 |> |53 ||PUSH EBX ; /RemoveMsg = PM_REMOVE|PM_NOYIELD|FFFFFFFC
004D1DCA |. |53 ||PUSH EBX ; |MsgFilterMax = MSG(FFFFFFFF)
004D1DCB |. |53 ||PUSH EBX ; |MsgFilterMin = MSG(FFFFFFFF)
004D1DCC |. |53 ||PUSH EBX ; |hWnd = FFFFFFFF
004D1DCD |. |55 ||PUSH EBP ; |pMsg = 0012FFC0
004D1DCE |. |FF15 F0C74F00 ||CALL DWORD PTR DS:[<&USER32.PeekMessageA>; \PeekMessageA
004D1DD4 |. |85C0 ||TEST EAX,EAX ; appname.004FE4B0
004D1DD6 |.^\75 D0 |\JNZ SHORT appname.004D1DA8

This code snippet is what I've narrowed it down to. It loops, and the line I've bolded is a call that draws components on the main window. Before this there was a call to display the actual window, but with no toolbar, scroll bar, etc. This function is what draws all of those components. However, after numerous loops, one call to this bolded function displays the nag dialog (without components). Subsequent calls to the same function draw the components (labels, buttons, etc) into the nag dialog.

The bolded function in question:
Code:

004D2254 . 56 PUSH ESI ; appname.005307D8
004D2255 . 8BF1 MOV ESI,ECX ; appname.005307D8
004D2257 . 33C0 XOR EAX,EAX ; appname.004FE4B0
004D2259 . 57 PUSH EDI ; appname.005307D8
004D225A . 50 PUSH EAX ; /MsgFilterMax = 4FE4B0
004D225B . 8D7E 30 LEA EDI,DWORD PTR DS:[ESI+30] ; |
004D225E . 50 PUSH EAX ; |MsgFilterMin = 4FE4B0
004D225F . 50 PUSH EAX ; |hWnd = 004FE4B0
004D2260 . 57 PUSH EDI ; |pMsg = appname.005307D8
004D2261 . FF15 14C74F00 CALL DWORD PTR DS:[<&USER32.GetMessageA>] ; \GetMessageA
004D2267 . 85C0 TEST EAX,EAX ; appname.004FE4B0
004D2269 . 74 26 JE SHORT appname.004D2291
004D226B . 817E 34 6A030000 CMP DWORD PTR DS:[ESI+34],36A
004D2272 . 74 1A JE SHORT appname.004D228E
004D2274 . 8B06 MOV EAX,DWORD PTR DS:[ESI] ; appname.004FE4B0
004D2276 . 57 PUSH EDI ; appname.005307D8
004D2277 . 8BCE MOV ECX,ESI ; appname.005307D8
004D2279 . FF50 58 CALL DWORD PTR DS:[EAX+58] ; appname.004D1FCA
004D227C . 85C0 TEST EAX,EAX ; appname.004FE4B0
004D227E . 75 0E JNZ SHORT appname.004D228E
004D2280 . 57 PUSH EDI ; /pMsg = WM_CREATE hw = 4FE4B0 pCreate = NULL
004D2281 . FF15 18C74F00 CALL DWORD PTR DS:[<&USER32.TranslateMessa>; \TranslateMessage
004D2287 . 57 PUSH EDI ; /pMsg = WM_CREATE hw = 4FE4B0 pCreate = NULL
004D2288 . FF15 ECC74F00 CALL DWORD PTR DS:[<&USER32.DispatchMessag>; \DispatchMessageA
004D228E > 6A 01 PUSH 1
004D2290 . 58 POP EAX ; appname.004D17B5
004D2291 > 5F POP EDI ; appname.004D17B5
004D2292 . 5E POP ESI ; appname.004D17B5
004D2293 . C3 RETN


My question is...what is this function doing? How can it get creation messages for these components on the fly? Also a tidbit about this function, once all the components are drawn on everything, Olly shows "running". As soon as I move my mouse to the application, Olly immediately breaks on the 4D1DAC line, where I have a software breakpoint. This means that the function is also handling waiting for user input?

Thanks in advance for any pointers, or indeed any information whatsoever.

blabberer
November 13th, 2008, 01:31
that is the classic message loop it simply recieves (PeekMessage(),TranslateMessage(),....,....,...) and passes it to the handler (DispatchMessage,PostMessage,SendMessage(),....,....,)

you need to find the callback thats handlind these messages

Externalist
November 16th, 2008, 19:48
Import the symbols for mfc*.dll into your olly and look for CCmdTarget::OnCmdMsg. That's where all your message for every window is being processed. You can set a conditional bp on the call to AfxFindMessageEntry to filter only the messages of your interest and work from there...