I am trying to inject my .dll into another process... So I found out that you can just hook the dll and it will map into the other process memory space. Easy enough... but my .dll has no exports to CALLBACK to. Thus I tried to add in Megatron's code about how he hooked the notepad edit area:
Sitting w/ Bob Status: -Next -To- Null- Friend: Philip
Posts
1,152
Re: .dll question
I think someone needs to make a zip with sample projects in VB including the c++ dll source, of hooking another application and responding to messages. It seems all the questions in this forum lately have been directed towards this.
:::`DISCLAIMER`:::
Do NOT take anything i have posted to be truthful in any way, shape or form.
Thank You!
-------------------------------- "Never heard about "hiking" poles. I usualy just grab a stick from the nature, and use that as a pole." - NoteMe "Finaly I can look as gay as I want..." - NoteMe
Languages: VB6, BASIC, Java, C#. C++
Sitting w/ Bob Status: -Next -To- Null- Friend: Philip
Posts
1,152
Re: .dll question
his project uses an active x control that handles the hooking i do believe.
avoids alot of the trouble which people have with this...but they will learn nothing from it then.
:::`DISCLAIMER`:::
Do NOT take anything i have posted to be truthful in any way, shape or form.
Thank You!
-------------------------------- "Never heard about "hiking" poles. I usualy just grab a stick from the nature, and use that as a pole." - NoteMe "Finaly I can look as gay as I want..." - NoteMe
Languages: VB6, BASIC, Java, C#. C++
his project uses an active x control that handles the hooking i do believe. avoids alot of the trouble which people have with this...but they will learn nothing from it then.
But the source is included, so learn away!
This however is not the solution to Lyric's problem.
The only reason the hooking programs inject themselves is that the external App has to call the GetMsgProc of your dll when a message arrives.
This won't work for you since you're not relying on message arrival. Take a look at the DebugInjector class in the APISPYLD example.
Here the code is injected on Debug assertions which can be forced.
I don't have an export in my .dll as I explained. However I can use just some really simple .dll to hook and get it in the process's memory. I then just use a LoadLibrary call from that simple .dll and it should load the real .dll into the same address space. Here is the problem. When you do call loadlibrary the .dll is mapped into the address space. However it isn't actually put in there until something is used from the .dll and it has to be moved in. Thus, I have to create some type of function call pointer to the .dll. I am here so far: (This is the code in the simple .dll that is already in the process address space and now is making a fake function call just to get the .dll loaded)
theDll = LoadLibrary("D:\myDLL.dll");
fakeHandle = GetProcAddress(theDll, "DummyFunction");
funcPtr = fakeHandle; //here is the problem
fakeReturn = funcPtr(8);
error C2064: term does not evaluate to a function
Error executing cl.exe.
or
cannot convert from 'int' to 'int (__cdecl *)(int)'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
The function I am pointing to called DummyFunction takes on one int parameter and returns a BOOL.
This however is not the solution to Lyric's problem.
The only reason the hooking programs inject themselves is that the external App has to call the GetMsgProc of your dll when a message arrives.
This won't work for you since you're not relying on message arrival. Take a look at the DebugInjector class in the APISPYLD example.
Here the code is injected on Debug assertions which can be forced.
...
...
I want to attach to the process and not be forced to load it through a loader program. I am not sure if that is what this is doing for sure...but I know that APISPYLD makes you load the .exe and not just attach to it. However I will look through it and see if maybe I can draw something from it.
Maybe I am a complete idiot now... in order to use a function from a .dll it must be in the export section of the .dll. Thus in order to call this fake function...it must be labeled as an export. is this correct?
I tried combining them and I got nothing but errors. Of course I am sure it is because I didn't have the proper layout for combining them. Maybe you can tell me the proper way to combine:
The normal APISPY32.dll project and this: ( I got the function pointer to compile, but it crashes when the .dll is loaded. I assume it never finds the correct pointer, because the function it is looking for is not an export, and when it makes a call to the function it just crashes. Thus I removed it from this code as this is a different method anyway)
'Receives the address of the GetMsgProc function, which will be imported
Dim lpfn As Long
'Loads our DLL into memory. Change the path to the path of your DLL
hModule = LoadLibrary("D:\Documents and Settings\Administrator\Desktop\base.dll")
If hModule <> 0 Then
'Retrieve the address of the GetMsgProc function in our DLL
lpfn = GetProcAddress(hModule, "_GetMsgProc@12")
'Install the WH_GETMESSAGE hook
If lpfn <> 0 Then hHook = SetWindowsHookEx(WH_GETMESSAGE, lpfn, hModule, 0)
Else
MsgBox "Cannot load module"
End If
End Sub
Then the .dll I load is in the memory space and I hope that once inside it will start reading the API's as normal. Which I assume it will do as it worked before. The .dll I load is still up for grabs as nothing has worked yet. I have read an article on code project ( http://www.codeproject.com/threads/winspy.asp ) and they use 2 .dlls as I was earlier. I dont really care how it works to be honest. The system performance does not seem to be to far reduced with the hook staying there anyway.
I'm still unclear as to where and when you're trying to do things
1. hook External App - why do you need a hook?
2. load 2nd dll - why not combine the two dlls into one?
You can't just load the APISPY32.dll into the memory space of the external app and expect it to work if that is what you're planning. You have to go through all the steps in APISPYDL.exe.
I'm still unclear as to where and when you're trying to do things
1. hook External App - why do you need a hook?
2. load 2nd dll - why not combine the two dlls into one?
You can't just load the APISPY32.dll into the memory space of the external app and expect it to work if that is what you're planning. You have to go through all the steps in APISPYDL.exe.
1. you have to use hooks to load into a different process addresss space unless you execute the program yourself (which I want to attach and not execute so hooks are the way to go)
2. i tried that, my error is shown a few posts up
Also, I think that it is possible that apispy32.dll can run independent of the loader. you could be completely correct, but here me out. all the loader does is put the dll into the address space. it doesnt even access the functions in the .dll. I put a messagebox for when it gets a hook on a DrawText and it displays the text in the messagebox. Currently I have a system wide hook and when I execute the program it hooks itself also. When I close the app it displays a few messageboxes that I assume meet the specifications for being a DrawText API call and having 0xFFFFFFFF as the third parameter (meaning it is drawn to a picture and not a text box). Even if it isn't messaging correctly, just the fact that I know it gets to that part of the code means that it is doing some API hooking and is executing the APISPY32.dll.
you have to use hooks to load into a different process addresss space unless you execute the program yourself
Not true. You might be able to replace the CreateProcess call in APISPYLD with a call to DebugActiveProcess.
The APISPYLD.exe is mainly responsible for doing the injection. Injection is more than just loading the dll into the address space of the external process. The routine that does the injection is CDebugInjector::PlaceInjectionStub
You've got to do these steps to do the injection yourself
1. Locate where the stub will be in the target process
2. Copy the stub into the target process
3. Change the EIP register in the target thread to point at the stub we just copied in.
I think there is a little problem with my above method.
The apispy initialization takes place in the process_Attach section of dllMain. This means that it will happen both for the external app as well as the VB app.
We need to move those calls to the message handling section and perform them upon receipt of a user defined message that we will send from VB. I'll try that when I get a chance.
OK, I've got it and have attached working code below.
As mentioned above, I added some subroutines to APISPY32.c
I modified the DllMain routine to keep APISPY from installing when the dll
attaches to the VB end of things
Code:
case DLL_PROCESS_ATTACH:
HInstance = hInst;
FChicago = (BOOL)((GetVersion() & 0xC0000000) == 0xC0000000);
if (hWndVB > 0){//only do this for external process
if ( InitializeAPISpy32() == FALSE )
return 0;
if ( InitThreadReturnStack() == FALSE )
return 0;
hWndSPY = hInst;//mark this instance
}
break;
case DLL_THREAD_ATTACH:
if (HInstance = hWndSPY)
if ( InitThreadReturnStack() == FALSE )
return 0;
break;
case DLL_THREAD_DETACH:
if (HInstance = hWndSPY)
if ( ShutdownThreadReturnStack() == FALSE )
return 0;
break;
case DLL_PROCESS_DETACH:
if (HInstance = hWndSPY){
ShutDownAPISpy32();
ShutdownThreadReturnStack();
if (hhookHooks != 0){
result = UnhookWindowsHookEx(hhookHooks); hhookHooks = 0;
hWndVB = 0;
}
}
break;
Added two exported functions to be called from VB:
A function to Set a hook from VB; we pass to it the ThreadID to hook as well as a handle to a window in VB to receive callback messages from dll.
Code:
__declspec(dllexport) int _stdcall InstallFilterDLL(DWORD dwThreadId, HANDLE hWndReturn)
{
if (hhookHooks==0)
hhookHooks = SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC) CallWndProc, (HINSTANCE)
HInstance, dwThreadId);
if (hhookHooks==0) return GetLastError();
hWndVB = hWndReturn;
return 0;
}
And one to remove the hook
Code:
__declspec(dllexport) int UnInstallFilterDLL(void)
{
LRESULT result;
if (hhookHooks != 0){
result = UnhookWindowsHookEx(hhookHooks);
hhookHooks = 0;
hWndVB = 0;
}
return 0;
}
The Window Procedure function for monitoring the messages
Currently it only serves to monitor for shutdown of target app
Code:
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CWPSTRUCT *lpMsg;
LRESULT result = 0;
//return immediately for negative nCodes
if (nCode >= 0){
if (nCode==HC_ACTION){
lpMsg = (CWPSTRUCT *) lParam;
switch (lpMsg->message){
case WM_CLOSE://we're shutting down
//notify VB we're shutting down
if (hWndVB>0) SendMessage(hWndVB, UM_STOP, 0, (LPARAM)result);
//remove the hook
if (hhookHooks != 0){
result = UnhookWindowsHookEx(hhookHooks);
hhookHooks = 0;
hWndVB = 0;
}
break;
}//end switch
}//end HC_ACTION
}//end nCode >=0
return(CallNextHookEx(hhookHooks, nCode, wParam, lParam));
}
Here we have three two user-defined messages and two other constants
Code:
#define UM_STOP WM_USER + 0x101 //message from dll to VB; dll is shutting down
#define UM_ERROR WM_USER + 0x102 //message sent from dll to VB; an error has occurred
#define ERR_INITSPY 1 //Error type; InitializeAPISpy32 failed
#define ERR_INITTHREAD 2 //Error type; InitThreadReturnStack failed
uhhhh....wow! I haven't been on the boards for about 3 days now because I have had sooo much damn school work to do. I will be able to give this a try tomorrow and get back with you. Thanks a lot for your help!
I used the exact project from your zip and the C++ section doesn't actually compile the .dll. It puts APISPY32.exp and APISPY32.lib into the debug directory where the .dll would normally be. Something I have set wrong or what?
Wasn't added correctly...I GOT IT! Also I just wanted to add that right before you posted your great solution and I was using the 2 .dll method, I did in fact get it working. All you have to do is get the APISPY into the address space and it does in fact take over from there. This is obviously much better so forget it... Thanks and now I will be up allll night =P
I got it to monitor the APIs and it turns out it does it perfectly, but then crashes when you close one of the apps from what I assume are CopyData calls. The error message talks about unreferenced memory and memory trying to be "read" and something "wrote". Thus I assume it has to be this call. Trying to find a better way to disable.
I am actually trying right now to just leave the .dll in the process and just not have it send out messages after the vb app closes. That has not worked either. Another problem could be it isn't replacing the IAT table back. Thus the functions never get rerouted to the actual correct spot in USER32.dll
***** Update
Dont know why I didn't think of this first...but i removed the Copydata call and it still crashes. Now I assume it is the IAT. If not that then....damn out of ideas.
Last edited by Lyric8; Feb 15th, 2005 at 03:21 PM.
..., but then crashes when you close one of the apps
Damn! I thought I fixed that.
Use the shutdownapi command provided and it works fine.
I don't understand.??? Are you saying get rid of the changes I made to shutdownapi or what?
Exactly what changes did you make so that it exits gracefully?
I had everything working great. Then I went and played some hoop, come back and now it acts like it is complete ****. I can't even really compile changes anymore and it wont work on another machine because of the .ocx **** (in the future I will avoid .ocx like the clap). I don't even know where I am anymore. Is there some way to just keep this version control **** out of my life?
Is the .ocx really needed? It seems to be nothing but problems thus far... I cant even properly load or compile with it saying it cant load the .ocx. It is in the correct path and everything. no dice...
Last edited by Lyric8; Feb 15th, 2005 at 07:21 PM.
here is the error that was dumped to Form1.log when the project fails:
Line 12: Class SubClass.subClassControl of control subClass was not a loaded control class.
I found the version control option and turned that off...still....no dice
ALSO...when i finally get it to get into project mode and not saying that it didnt load the .ocx. It gives me this error ( I assume this is the first line that it reads that is undefined because it never really loaded the .ocx functions)
Compile error
Method or data member not found:
subClass.Enable 0
Last edited by Lyric8; Feb 15th, 2005 at 07:34 PM.
I'll rewrite the control as a class instead
In the meantime.
open the project, choose OK on all errors
open the form with the control on it, OK on all errors
delete the control from the form
Add it back to the form and name it SubClass
if you want to compile it, you'll have to
compile the ActiveX control project,
select binary compatibilty, choosing the OCX you just compiled
recompile the activex control project
compile the main project
I'm working on fixing the crashes.
I think it's related to removing the hook If you add a remove hook button to the VB form, press it, then when you move the mouse over your external app your external app will crash.
I also discovered some errors in my code and some stupid things I did, but still haven't gotten rid of the crash.
The problem seems to be an interaction between the APISPY initialization and the hook.
The solution is don't ever remove the hook. This is OK since if the VB program is shutting down, the dll knows not to send messages anymore. If the dll is shutting down, then the hook goes away anyway. So, remove all calls to UnInstallFilterDLL from the VB app.
Attached is an improved APISPY32.c source with calls to UnhookWindowsHookEx removed and some bugs fixed.
There is a problem in programs that spawn other windows. For example if you tried this on a vb app that had lots of forms and you attached to one of the secondary forms, then when you close the secondary form and try return to main it will crash.
***Update
Unless you close the vb app and then close the secondary window.
Last edited by Lyric8; Feb 18th, 2005 at 06:20 PM.