I am trying to set up a hook to monitor a different app and get the parameters of a certain API call when it is made. I am trying to be certain that I don't need to inject a .dll for this. It seems that API monitors can attach to other processes just fine and I have the API down to get threadID, ProcessID and everything like that. I can do hooks to my own application for capturing keyboard events and things like that. I know this topic is brought up all the time and it just never gets finished...the everlasting API monitor
Thanks a lot and these boards are NICE!
PS - I read the post "Log text from WM_SETTEXT messages like Spy++ [Theoretically RESOLVED]" and it seems like that could almost be partially used for this. I am not sure how the message handling and the API calls are related.
Last edited by Lyric8; Jan 24th, 2005 at 07:23 AM.
As it turns out, it is even easier than before. I have been using Windbg and have lots more info! Hopefully someone can help me tie this all together. Basically RtlMultiByteToUnicodeN makes a few other API calls and so I used one of the later calls that has an address of a ANSI string. The new API call I need to have an exception/break on is DrawTextA which is user32.dll. The structure of the paramters for DrawText looks like this:
int DrawText(
HDC hDC, // handle to DC
LPCTSTR lpString, // text to draw
int nCount, // text length
LPRECT lpRect, // formatting dimensions
UINT uFormat // text-drawing options
);
Thus if I can just get that pointer in parameter 2 read into my app each time the other app calls it, I have my string I want.
It sounds to me like you are talking about a debugger, which is what Windbg smells like. If the app you want to monitor is not written by you, you may have problems because we compile in debug mode and release mode which I believe enables the so-called api hooks you are looking for.
But even if the monitored app is not written by you, it should be possible to see function calls. Sounds like reverse engineering and assembly language.
I may also need that because some of the apps I'd like to monitor do not have a direct HWND to watch for the messages. It may be something drawn like you mentioned.
Circa 1995
Engineer - I think we should put our website address on our paper catalogs.
Vice President - Don't get too excited about this internet thing.
I am sorry, but the Oracle was mistaken. You cannot help us.
-Matrix video game
I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) for 386(486) AT clones. ... and it probably never will support anything other than AT-harddisks, as that's all I have :-(.
-Linus
Question. Do you know that the character "?" means I'm asking a question? Question. Do you know that spoken inflection also provides the same cue? So please don't say, "Question" before you ask your question. Believe me I'll know.
That said, I would have said this first if it had to precede what I'm telling you now. Having said that, what I'm telling you now is the same thing I just said about the annoying phrases "That said" and "Having said that".
Are you threatening me, Master Jedi?
-Chancellor Palpatine
The messages that are drawn and dont have an actual handle or hWnd have a value of 0xFFFFFFFF (0xFFFFFFFF = -1?) in the 3rd parameter. If they do have a value for that parameter then the text is being written into some textbox or something like that, also then that parameter will hold the length of how many chars are drawn and not 0xFFFFFFFF. I would look it up again but I am running out the door. I am going to be working on this again in about 2 hrs and I will post back with it then. WinDbg is in fact a debugger and obviously so is Auto Debug for Windows. They can catch these API calls just fine. Will I have to code a sort of debugger then to catch API calls? I imagine that will not be very fun. I'll search for some code snippets of debuggers that can break on another apps API call and read the parameters off the stack. Thanks for replying...
Last edited by Lyric8; Jan 24th, 2005 at 08:43 PM.
Reason: was temporarily insane, made even less sense than now
Yes either a debugger or injecting a dll.
Ive done injected a few times, though it was C++.
If your doing with VB then debugging is probably your only way.
Dont think anyone can tell you more detailed as it would probably be against board rules.
Maybe I missed something about board rules, but why would this violate anything? There are many threads where people actually walk through code and post changes and such. Thanks
Sort of lost of what to even look for while attached to a process. Are API calls sent using post message or something like that? I don't see how I can get the information from this. I can now inject a .dll, hook, and subclass. Just lost on how all these things are used to see what API calls a function is making. I even read up on debuggers and I can see the pointer to the string on the stack whenever the debugger breaks on the API call. I just don't see how you know when to break or what flags are raised when there is an API call. The system DLLs aren't reloaded or anything....just lost. anyone?
Well now I better understand PE file structure and how the .dll and .exe interact. I guess I am just not making the connection on the whole thing. However I did just find a great example of API Spying that has source code. Only problem is that it was coded ages ago and I can't even get the project to work now. If your interested in this or can go through C++ pretty well, then have a look:
Only problem is that it was coded long ago when there was only a few API .dll's. I just need to expand it to include the USER32.dll and monitor the API call DrawTextA. If anyone can help I could really use it...I am past deadline and getting desperate for anything. Thanks a lot!
So, from reading the two documents, it looks like you have to locate the API function you want to monitor in the executable's Import Addrres table. Get the pointer to the function and replace it with yours.
Unfortunately, you still have to write a C++ dll to insert your own routine since you need to be in the address space of the EXE.
The procedure is similar to the previous post you mentioned on Hooking external apps (sometimes incorrectly refferred to as Subclassing), but instead of hooking into the message pump, you're hooking into the jump table. Subclassing hooks the Window Procedure.
I suppose now you've realized that calling API functions does not involve Win dows messages but instead relies on a jump table.
You could write a few "simple" C++ functions to set the hooks and then call your VB App. This would involve sending messages back to you VB App.
One C++ function to create would be
HookAPI (APIfn as String, VBhWnd as Long)
Your pretty much correct.
you could hook an api and maybe replace the pointer with a pointer to a function in a vb exe. But you would have to know the number of parameters and thier types.
So a single function like this just wouldnt work for all api's.
HookAPI (APIfn as Long, OutOwnfn as Long,VBhWnd as Long)
Without knowing the parameters and type the stack would get currupt and you would most definetly crash both applications.
Since I am just monitoring a single API call on this particular application then if I do the method that was mentioned by moeur by replacing the function pointer in the IAT with my function, then I point back to my vb application using CALLBACK and the stack contents I do infact know. I looked up my api call on msdn:
int DrawText(
HDC hDC, // handle to DC
LPCTSTR lpString, // text to draw
int nCount, // text length
LPRECT lpRect, // formatting dimensions
UINT uFormat // text-drawing options
);
Since I am just trying to get the string I can pop the first 3 parameters and store/use them. The first is the return address, second is the handle to DC, 3rd is the string i want. I then read out the ANSI string pointer in memory and save it in my program. Now I push the items back on the stack in reverse order so the return address is last and then i sort of get lost (as though I can actually do most of what I said before). Do I callnexthook in the vb app or somehow point the next Proc to the actual location of the API call that i replaced in the IAT. The stack would be correct and the function would never even know it was intercepted. Ok...fire away!
I don't think that you can accomplish a callback to your VB App since it is in a different address space and addresses in one space don't make sense in another.
I think the easiest thing to do is the following:
Once the hook is made, your C++ routine gets called insted of the API call.
1. Have your C++ routine send a Windows message to your VB app which you have subclassed to receive such messages. This message can contain the data you are looking for.
2. VB processes the message and returns control to the C++ app
2. the C++ app now calls the original pointer that you replaced and saved somewhere. (Similar to calling the next hook)
I don't think that you can accomplish a callback to your VB App since it is in a different address space and addresses in one space don't make sense in another.
Good point...
I think the easiest thing to do is the following:
Once the hook is made, your C++ routine gets called insted of the API call.
1. Have your C++ routine send a Windows message to your VB app which you have subclassed to receive such messages. This message can contain the data you are looking for.
I think I can do this part
2. VB processes the message and returns control to the C++ app
I think it would work if I just used the SendMessage( custom msg vb app is looking for) and then do the next step without ever changing control or anything like that.
2. the C++ app now calls the original pointer that you replaced and saved somewhere. (Similar to calling the next hook)
not sure how I call a pointer but I assume I just get the stack to the correct position and then maybe use assembly call to just "Jump addressofcorrectIATpointer". Also when you say C++ app do you really mean a sort of app or just the .dll that was injected?
I think it would work if I just used the SendMessage( custom msg vb app is looking for) and then do the next step without ever changing control or anything like that.
All I meant was that since sendmessage is synchronous, when you call sendmessage the process waits for the receiver to process the message before continuing. There is an API call you can make in the receiving process that tells the sender not to wait however. Postmessage is asynchronous, but you probably don't want to use that because you'll want to send more data than that can handle.
Also when you say C++ app do you really mean a sort of app or just the .dll that was injected?
Just the dll that was injected
not sure how I call a pointer
In C++ you just declare a function pointer. For Example:
Code:
long (*ptrFn)(long, long); //pointer to function that has two long parameters
Assign it to some value
Code:
ptrFn = savedvalue; //you might have to do some casting here
I don't think that you can accomplish a callback to your VB App since it is in a different address space and addresses in one space don't make sense in another.
This is like a small side project he was doing and is called Simonsez.c
It seems like this would be much easier to modify and use than his entire massive project.
Compiling...
Simonsez.c
c:\windows\desktop\apispy32\simonsez.c(47) : warning C4028: formal parameter 1 different from declaration
c:\windows\desktop\apispy32\simonsez.c(47) : warning C4028: formal parameter 2 different from declaration
Linking...
Simonsez.obj : error LNK2001: unresolved external symbol _HookImportedFunction@16
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/Simonsez.exe : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.
Your doing this all in c/c++ correct?
Or are you trying to combine it with vb.
Ive done this in asm and have coverted to c++, though the write access premissions is working correctly, if you would like to see it?
I would love to! I just finished a class in assembly and we had a pretty big project at the end. I haven't used C++ in a couple years so it makes less sense than your asm will. Thanks a lot!
I am trying to combine a vb message receive using the method already metioned and C++ .dll that gets injected. Hopefully I can find a way to inject the .dll by attaching to a thread and without starting the application I am trying to monitor through my application. I will worry about that later though . A walk of a million miles begins with a single step...
Some handsome, suave... blah, blah, blah... has written an article on the PE structure you can read here
Checking out this vb code, I noticed that the functions defined are not very useful since there are a lot of missing function and structure definitions. Some of the functions seem to be C++ functions.
Its called IATPATCH.zip under projects. Its in MASM.
I just changed it to work with MessageBoxA like it was suppose to be.
The project1.exe is a vb exe to load the dll using SetWindowsHookEx.
you can test it with the TestMsgBox.exe or make your own test as I didnt give source for it.
Sometimes it will crash explorer. As with all software on my site, you use at your own risk.
for some reason if you just have the 1 api call in the file then it never outputs anything. thus I just added an API call that is never made and the program was ok with it. only problem is that i cant get the source for this project in the .zip to actually load into a working C++ project. Anyone else have some luck?
;get the current security attrib for this mem location
invoke VirtualQuery,pIAT,addr mbi,sizeof mbi
;Ack somethings jacked if we get a zero here
.if eax==0
It was made it some other form of C++ I assume becuase it says it will update it to my verstion of VC6 and so when I click ok it says the files are corrupt and it fails. I am trying to find the correct files to just add to a project and compile it. However there is a damn makefile so you would think that would just work. That fails also...
;get the current security attrib for this mem location
invoke VirtualQuery,pIAT,addr mbi,sizeof mbi
;Ack somethings jacked if we get a zero here
.if eax==0
moeur does that mean you can get it into a VC++ project?
packetvb where do you state the name of the .exe you are injecting into? I cant find it anywhere. Is this supposed to be a system wide hook? I did a quick app that used message box as an API call and as just the normal vb msgbox and it didn't catch either. However it always catches the test app message box.
Its system wide.
It hooks the MessageBoxA from User32.dll.
It wont work with the msgbox from a vb created exe because the exe is linked with MSVBVM60.DLL not directly linked with USER32.DLL.
Also it wont work with a declared api, because still the exe only links with MSVBVM60.DLL which handles the api call.
It should be possible to go down into the MSVBVM60.DLL and hook it there. That would be a bit more difficult and would probably have unwanted side effects. It would be hooked for any app using MSVBVM60.DLL.
packetvb
Last edited by packetVB; Feb 3rd, 2005 at 01:03 PM.
The project 'APISPYLD.MAK' must be converted to the current Visual C++ project format. After it has been converted, you will not be able to edit this project in previous versions of Visual Studio.
Convert and open this project?
When I try to compile them individually I basically compile everything and this is the error in the debug window: If you have a working project in VC++ 6 could you zip it and maybe email it to me or something? [email protected] THANKS!
To recompile the APISPY32.DLL we need to compile the ASM file which means I have to dig out my MASM6.11 floppy disk and DOS disks. Once we get an OBJ file from the ASM file then I think we're OK.
But, don't you want to just play with APISPYLD.EXE? If so, the make file works for that and you can create a C++ project:
1. Create a new Win32 Application
2. Add Files APISPYLD.cpp, APISPY32.H, DebugInjector.cpp and DebugInjector.h
3. go to project settings and change settings as follows
WIN32Debug