Hey guys.. I'm not sure if this is a 'quick' question or not, but I'm going to hope for the best.. ;)
I have a program that im trying to write which will look for an open AIM window and subclass its edit control class "Ate32Class" so that I can intercept the WM_CHAR message and play a sound whenever someone types (like icq).
Now apparently I have to use some method other than what i'm currently doing, which is getting the handle of the edit box class and then subclasses it with SetWindowLong.

One thing to note: I know that the handle that I receive for the edit box class is valid because I can send text to it through SendMessage with WM_SETTEXT.

Here's how I threw it together, basically:
1.) I have a menu item called IDM_KEY_SOUND:
elseif eax==IDM_KEY_SOUND
invoke FindEditWindow ;get the handle to the Ate32Class editbox
.if hAte32Class != NULL
invoke SetWindowLong, hAte32Class, GWL_WNDPROC, addr TextSoundProc ; subclass it
mov OldWndProc, eax ;store old procedure

2.) Inside I have a function FindEditWindow called:
FindEditWindow PROC
invoke FindIMWindow ;finds the actual AIM IM Window itself
.if eax != NULL
mov hIMWindow, eax ;store the handle inside
;This goes through the little tree of parent/child relationships for the controls in the window
invoke FindWindowEx, hIMWindow, NULL, addr lpWndAteClass, NULL
mov hWndAteClass, eax
invoke FindWindowEx, hIMWindow, hWndAteClass, addr lpWndAteClass, NULL
mov hWndAteClass, eax
invoke FindWindowEx,hWndAteClass, NULL, addr lpAte32Class, NULL
mov hAte32Class, eax ;this is the handle to our edit text box inside of the im window

FindEditWindow endp

3.) Inside this function I call the FindIMWindow function:
FindIMWindow PROC
invoke FindWindow, addr lpIMClass, NULL ;find our AIM IM Window
.if eax == NULL
invoke FindWindow, addr lpDIMClass, NULL ;Check for the DeadAIM IM Window
FindIMWindow endp

4.) And finally, here's the actual custom editbox procedure:
TextSoundProc PROC hEdit:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
.if uMsg ==WM_CHAR
invoke PlaySound, addr lpSoundFile, hInstance, 0
invoke CallWindowProc,OldWndProc,hEdit,uMsg,wParam,lParam
invoke CallWindowProc,OldWndProc,hEdit,uMsg,wParam,lParam
TextSoundProc endp

Now that is basically the code in a nutshell...
I didnt know if I had to somehow load aim with my program first and get some handle to its process before I could subclass its edit box or what I had to do.. Needless to say, I'm pretty confused...

Also, Whenever I run the code--nothing is called inside of the custom editbox subclass proc, like if i put a messagebox or anything inside, none of it is ever called.

Thanks guys for at least looking at it..
Posted on 2004-02-04 20:29:44 by dijo
If all else fails:

*) put your subclassing code in a DLL
*) inject DLL into AIM's process

This might be balancing at the edge of what is allowed at this board (stupid DMCA and all), but since it's pretty obvious you're not doing anything harmful and not really reversing anything, I guess it should be okay.

There's basically two ways of injecting a DLL - one is easy, the NT way... VirtualAllocEx + CreateRemoteThread. Under 9x, there's a hacky way, it's demonstrated by my XCOM bugfix loader at http://f0dder.has.it (C source, not asm). Oh, and there's EliCZ's stuff to emulate VirtualAllocEx+CreateRemoteThread under 9x...
Posted on 2004-02-04 20:39:52 by f0dder
I just wanted to say thanks for the help.
I've got the dll created with the 'proper' functions, I hope..
now all I have to do is read up on this dll injection, and then i'll hope for the best. =)

note: oh yeah, I can call the dll fine too. woohoo. ;)

^ looks pretty interesting, although perhaps a TAD difficult!
"Specify pointer to requested address." I thought that was pretty interesting..
I should probably read some tutorials which will build me up to this point.. I havent a clue on how much memory to allocate (although i could just create a ridiculous amount of space and hope for the best..) or where to point the address at.. but i'll keep looking. *just keeping you informed in case you were curious*

okay then..

I found some interesting things here on getting the handle and such... to the process
http://win32assembly.online.fr/w32_02.txt haha, yes i realize that's a popular site..
Posted on 2004-02-04 21:55:20 by dijo
Okay.. I guess im at a stand still at the moment. Apparently I need to use a pe viewer and find out where to put my code in, and im not exactly knowledgeable with such.. I'll probably try and find some good tutorials unless somebody could recommend a few.. and then there's using a debugger/disassembler (like ida/olly) which im not *too* familiar with..

fodder, i was amazed at how much you knew from reading the xcom essay.. that was pretty impressive.. if you have any idea on where you learned most of that stuff (minus the direct3d/x), i'd like to know so i can read up on it..

I'm pretty much just stuck here at the VirtualAllocEx.. I'm not sure what to put in for the values for that (because of what i mentioned above)...
Then i saw some suggestions for CreateProcess() with some debug flag so that I could write to the process's memory, but I havent a clue as to where i'd write to or what i'd write there even if i knew...

Gosh, I feel like such a newb! haha.. how embarrassing.
well, i'm trying.. I guess that's all I can do.

Thanks again for the help fodder.
Posted on 2004-02-04 23:22:42 by dijo
You can also use a Hook and watch for the target window beeing created .

The hook will resolve the DLL injection as the hook DLL is normaly injected by windows itself into each running process .... and is going to work the same way on both Win9x and Win2k/NT

Take care as you must be very carefull and minimalist in your hook or it can slow down the OS a lot. Also it might need shared data sections for global flags because each DLL has its own data zone in each process.

Also "theoretically" after you have found your window and have subclasses it .... you could remove the hook :grin:

But hellas this will remove your injected (via hook) DLL also ... so the hook will have to stay for as long AIM/whatever is running...
Posted on 2004-02-05 05:27:22 by BogdanOntanu
Hey! :)

When using VirtualAllocEx for this, you don't really care what adress you get inside the target process, so specify NULL to have windows find one for you. As for size, a single page (4096) bytes should be quite sufficient - what you want to put in the target process would be something like this:

call @@delta
pop edx
sub edx, offset @@delta

lea eax, [edx+libname]
push eax
call LoadLibrary
ret ; this will terminate your thread
libname db "mylibrary.dll",0

The "delta trick" makes your code position-independent, which is necessary since you don't know at which address you will be running inside the target process. Any data access needs to be done with delta... this is the reason I use DLLs for this, I can keep the injected delta-code to something as simple as the above, and put all the real stuff in a DLL that is written as usual.

Notice that this code is meant to be executed with CreateRemoteThread, and can thus be ended with a "ret". NT is so much nicer and simpler than 9x :)

If you want to do it the 9x way with CreateProcess, you need to use some PE tool to find the imagebase of your executable, and the header.AddressOfEntyPoint - that's where to write the code. If you don't understand the stuff in my XCOM loader though, I suggest you try the NT method first; it's much simpler.

Don't feel like too much of a newb, this is semi-complicated stuff.

I don't like hooks for this - it's a brute force and lazy method :)
Posted on 2004-02-05 05:37:18 by f0dder
Hi f0dder,

Well i agree that i am lazy and brute force sometimes :grin:

But my dumb question is: will this method of your's work with an application that is already running
ie is not started by me and where i have to hook multiple windows/controls created by the application at random times?

If it does i will be happy to learn another way and i will try to use your method instead of a brute force hook.

Honestly i do not like the hook either because i can not stop it and leave my DLL inside the target process.

But you have to admit that since is provided as a part of windows API it is much safer :grin:
and it works just the same on Win9x (and unfortunately my clients use a strange mix of OS'es)
Posted on 2004-02-05 05:47:01 by BogdanOntanu
VirtualAllocEx + CreateRemoteThread will work on running apps, the CreateProcess 9x workaround obviously requires you to start the process. However, EliCZ has made a library that provides VirtualAllocEx+CreateRemoteThread functionality under 9x...
Posted on 2004-02-05 06:09:13 by f0dder

Thank you for info.
Posted on 2004-02-05 06:23:19 by BogdanOntanu
Posted on 2004-02-05 07:28:47 by stormix
Thanks for the info stormix.
I found this too; it seems pretty good..
Posted on 2004-02-05 09:05:28 by dijo
Why would he want to load a library or create a thread? Under Windows NT, he can use VirtualAllocEx and WriteProcessMemory. Under Windows 9X, he can go into Ring0 and allocate memory at a high address. When the code is present in the other program's address space, a WM_TIMER message can be sent to run it. This code can then call SetWindowLong to subclass the window. It's very simple!
Posted on 2004-02-07 05:28:58 by Sephiroth3

Under Windows 9X, he can go into Ring0 and allocate memory at a high address.

Why would he want to go into Ring0? Under Windows 9x he can allocate shared memory by giving VirtualAlloc the 08000000h flag. It's very simple!
Posted on 2004-02-07 06:07:33 by stormix
I just wanted to show you guys a nice link that I found for masm
It seems to be pretty nice.. :)
Posted on 2004-02-07 10:11:45 by dijo
Ah, I didn't know you could do that. I must have overlooked it.
Posted on 2004-02-07 12:23:09 by Sephiroth3