[VB6] - Multithreading in VB6 part 3 - DLL injection.
Hello everyone! This part is rather more about DLL injections than about threading as such, but because DLL can run programs with different numbers of threads I made this as a continuation of the theme of multi-threading in VB6. In the last article, I wrote about the possibility of creating a thread in the DLL, and the method of creating a native DLL for VB6. I also wrote that such a DLL will work in any application, but did not result in an example. In this section we will write a DLL that will be performed in another 32-bit process and execute our code there. As an example, make an application that will perform subclassing a window in another thread and send messages in our application that we can handle. Write once - DLL for example only and is not intended for use in applications as There are disadvantages to minimize code as I did not eliminate.
I decided to make use of 3 cases:
Limiting the minimum size overlapping windows.
Tracking button press/release the mouse in the window.
Log messages.
So, first you need to come up with a interaction mechanism between processes. I decided to go the following way:
For the exchange of data between applications will use FileMapping.
To send a message from the proces- "victim" to our application, we will use a new recorded message.
For notification of completion subclassing will transmit a message to the other side.
Now you need to consider how to implement the launch. Put the hook "WH_GETMESSAGE" on a thread that contains the window. Now our DLL is loaded into the address space of the process of the victim. In the callback function "GetMsgProc" the first call will initialize the data and set the desired window subclassing to exchange as mentioned above use the file-mapping. So the code:
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
We analyze in detail the code. In the initialisation procedure, check the flags initialization and shutdown subclassing. If any True, the means or subclassing installed or completed. Otherwise, start initialization. The first step is open the file-mapping and project views of the process address space. To avoid race conditions using mutex synchronization objects. Then register the message "WM_SENDMESSAGE" to exchange in the system and get his number. To store the address of the previous window procedure, I decided to use the property window, but could be used and a variable module, since at a time can only intercept only one window in this embodiment. For faster access to the property, I use the atom, so register it with the name "prevProc". Then try to acquire the mutex. When it works, the general data are available only for that thread, no other thread will not be able to record something there and we will avoid race conditions. From file-mapping we obtain the needed data (handle of the main window of our application, handle the "window-subclassing" hook and handle, it must pass a "CallNextHookEx"). Later releases the mutex, and set the address of the window procedure in our (directly subclassing). Now all the messages intended for the window will go to the procedure "WndProc".* We analyze the procedure "WndProc". To start analyze the structure of the file-mapping:
Check the message if it is our registered, it can only send our application when removing subclassing, so execute deinitialization. Otherwise, we form the message data and capture a mutex, write them to a file mapping with offset 0x0Ch (1210) and transmits them to the main window of our application for processing. Because we use the "SendMessage" for the transfer, leaving it will not happen until we are in your application does not finish processing the message. When you return the check flag "defCall", which is responsible whether to let a message on the old window procedure or not.
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
We analyze in detail the code. When loading forms call the "Initialize", which initializes the data necessary for subclassing. First create a mutex for synchronization, file-mapping for data exchange and project his presentation, recording a message "WM_SENDMESSAGE", load the library with the procedure hook and subclass the main window to receive messages. Further, when the success of the icon to load and load conditions subclassing a list of messages.
To start subclassing need to hold down the mouse button on the control "picIcon" and move it to the desired control. When this is getting the handle of the window under the cursor and mark frame. Frame for a window region is taken or if it exists, otherwise it is created on the basis of the window rectangle. Region outlines frame through "R2_XOR" overlay (vbXorPen), to remove the mark just once, a frame. When you release the button on the window, we handle it and run the function "StartSubclass". In this procedure, we check the thread (in its own thread, I forbade intercept messages can occur because recursion and departure), if necessary, set the subclassing. Next, open the process- "victim" because we need to read and write in the address space of the processing of messages passing flags "PROCESS_VM_OPERATION", "PROCESS_VM_WRITE", "PROCESS_VM_READ". Now to start subclassing need to prepare data for proces- "victim", so grab the mutex and then set the hook "WH_GETMESSAGE" in the thread proces- "victim". After that, copy the data into shared memory can be sure that the thread - "victim" will not be there to read. Even if the procedure "GetMsgProc" starts its execution, it will be waiting in the function "WaitForSingleObject" until we liberate the mutex. After copying releases the mutex, now everything is ready.
After receiving the next message window victim, we pass it to our application of the procedure "WndProc" located in the DLL, which is loaded into the address space of the victim. In our application we have in the preparation of "WM_SENDMESSAGE" copy the data from the shared memory and transmits them to the processing method of the form "WndProc". In this method, we selected depending tabs anyway processes the message. In the first case we limit the minimum Ramer windows, by processing the message "WM_GETMINMAXINFO". It must be remembered that the addresses passed to the window procedure - this is the address in the address space proces- "victim" for our process, they are invalid. Because of this, we instead "CopyMemory" use "ReadProcessMemory" and "WriteProcessMemory". In the second processing "WM_LBUTTONDOWN" and "WM_LBUTTONUP" and in his course mark tab. Thirdly just set the name of the message and the list of parameters.
To stop subclassing need to click on the icon that will be marked as "STOP". Thus, the function is called "StopSubclass". In it we pass the message window victim "WM_SENDMESSAGE", thereby saying that we end up subclassing. In the DLL, in the function "WndProc", as I described above, we produce deinitialization. After deinitialization returns to our application and removed the hook by calling "UnhookWindowsHookEx". After our system unloads the DLL from memory process victim.
As we have seen - DLL, written in VB6, works fine in other people's programs and threads. This DLL is written only for testing and demonstration opportunities VB6. I did not set myself the task of writing a complete DLL for use in projects, so deliberately DLL has limitations and has an irregular architecture (you can not make multiple subclassing and other limitations and bugs), there are no checks. To demonstrate the capabilities of this enough.
___________________________________________________________________________________________
How could we be sure that it is running in multi-threaded programs written in VB6, and DLL, written in VB6 work in any program. Thank you for your attention, good luck.
Last edited by The trick; Aug 22nd, 2016 at 04:48 PM.
Also, the strings seem to be russian language (or something similar), unreadable for other users.
i.e. when I load your project TestSubClassDLL in tabMain control I get this: Ìèíèìàëüíûé ðàçìåð îêíà
Please translate your strings, comments, etc... in english language, otherwise your projects are unusable.
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
now I write a dll set hook WH_KEYBOARD.and have a form in this dll . I inject this dll to one program. but if I show the dll form.the program will die.
can you have a demo to inject dll and show form?
thanks sir. my poor English .i hope you can understand .
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
Code:
' // Hook procedure
Public HomeCOUNT As Long
Public Function GetMsgProc(ByVal code As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
'
If wParam = vbKeyHome Then
If lParam And &H40000000 Then
HomeCOUNT = HomeCOUNT + 1
If HomeCOUNT = 1 Then
Form1.Show
GoTo mm
End If
If (HomeCOUNT Mod 2) = 0 Then
Form1.Visible = False
Else
Form1.Visible = True
End If
End If
End If
mm:
' // Call the next hook chain
GetMsgProc = CallNextHookEx(hHook, code, wParam, lParam)
Code:
'
Private Const WH_KEYBOARD As Long = 2
// Subclass window
Public Function StartSubclass( _
ByVal hwnd As Long) As Long
...
....
' // Install hook to receive messages in the specified thread
hHook = SetWindowsHookEx(WH_KEYBOARD, lpProc, hLib, TID)
...
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
Code:
' // Hook procedure
Public HomeCOUNT As Long
Public Function GetMsgProc(ByVal code As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
'
If wParam = vbKeyHome Then
If lParam And &H40000000 Then
HomeCOUNT = HomeCOUNT + 1
If HomeCOUNT = 1 Then
Form1.Show
GoTo mm
End If
If (HomeCOUNT Mod 2) = 0 Then
Form1.Visible = False
Else
Form1.Visible = True
End If
End If
End If
mm:
' // Call the next hook chain
GetMsgProc = CallNextHookEx(hHook, code, wParam, lParam)
Code:
'
Private Const WH_KEYBOARD As Long = 2
// Subclass window
Public Function StartSubclass( _
ByVal hwnd As Long) As Long
...
....
' // Install hook to receive messages in the specified thread
hHook = SetWindowsHookEx(WH_KEYBOARD, lpProc, hLib, TID)
...
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
Originally Posted by The trick
We analyze in detail the code. When loading forms call the "Initialize", which initializes the data necessary for subclassing. First create a mutex for synchronization, file-mapping for data exchange and project his presentation, recording a message "WM_SENDMESSAGE", load the library with the procedure hook and subclass the main window to receive messages. Further, when the success of the icon to load and load conditions subclassing a list of messages.
To start subclassing need to hold down the mouse button on the control "picIcon" and move it to the desired control. When this is getting the handle of the window under the cursor and mark frame. Frame for a window region is taken or if it exists, otherwise it is created on the basis of the window rectangle. Region outlines frame through "R2_XOR" overlay (vbXorPen), to remove the mark just once, a frame. When you release the button on the window, we handle it and run the function "StartSubclass". In this procedure, we check the thread (in its own thread, I forbade intercept messages can occur because recursion and departure), if necessary, set the subclassing. Next, open the process- "victim" because we need to read and write in the address space of the processing of messages passing flags "PROCESS_VM_OPERATION", "PROCESS_VM_WRITE", "PROCESS_VM_READ". Now to start subclassing need to prepare data for proces- "victim", so grab the mutex and then set the hook "WH_GETMESSAGE" in the thread proces- "victim". After that, copy the data into shared memory can be sure that the thread - "victim" will not be there to read. Even if the procedure "GetMsgProc" starts its execution, it will be waiting in the function "WaitForSingleObject" until we liberate the mutex. After copying releases the mutex, now everything is ready.
After receiving the next message window victim, we pass it to our application of the procedure "WndProc" located in the DLL, which is loaded into the address space of the victim. In our application we have in the preparation of "WM_SENDMESSAGE" copy the data from the shared memory and transmits them to the processing method of the form "WndProc". In this method, we selected depending tabs anyway processes the message. In the first case we limit the minimum Ramer windows, by processing the message "WM_GETMINMAXINFO". It must be remembered that the addresses passed to the window procedure - this is the address in the address space proces- "victim" for our process, they are invalid. Because of this, we instead "CopyMemory" use "ReadProcessMemory" and "WriteProcessMemory". In the second processing "WM_LBUTTONDOWN" and "WM_LBUTTONUP" and in his course mark tab. Thirdly just set the name of the message and the list of parameters.
To stop subclassing need to click on the icon that will be marked as "STOP". Thus, the function is called "StopSubclass". In it we pass the message window victim "WM_SENDMESSAGE", thereby saying that we end up subclassing. In the DLL, in the function "WndProc", as I described above, we produce deinitialization. After deinitialization returns to our application and removed the hook by calling "UnhookWindowsHookEx". After our system unloads the DLL from memory process victim.
As we have seen - DLL, written in VB6, works fine in other people's programs and threads. This DLL is written only for testing and demonstration opportunities VB6. I did not set myself the task of writing a complete DLL for use in projects, so deliberately DLL has limitations and has an irregular architecture (you can not make multiple subclassing and other limitations and bugs), there are no checks. To demonstrate the capabilities of this enough.
___________________________________________________________________________________________
How could we be sure that it is running in multi-threaded programs written in VB6, and DLL, written in VB6 work in any program. Thank you for your attention, good luck.
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
Originally Posted by The trick
What's Case uMsg = WM_SENDMESSAGE?
All come from your code, I just modified some parts and added judgments
Private WM_SENDMESSAGE As Long ' // Our message for exchange with the main application. By sending from the current thread
' // this message to the main application (TestSubclassDLL) we notify the application using
' // SendMessage that new message has been received. This message has the parameters which
' // stored to the file mapping. If we'll pass the message from the main application we notify
' // that it's necessary to remove subbclassing and uninitialize data.
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
in my pc work well. but can't run in other pc. if I used timer control to find which Window handle i will hook .the function findhwnd form herehWndFromPartTitle
Last edited by xxdoc123; Jan 7th, 2021 at 03:36 AM.
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
Originally Posted by The trick
Until there is a normal example showing the problem, I won't help you.
I want to automatically open the hook after finding the handle used loop through the timer control,Your example is to find
the handle through spy.if timer set true.do....loop find hwnd runed,but Program crashed
Download attachments
The weather is so cold, my computer is frozen!~~``
Re: [VB6] - Multithreading in VB6 part 3 - DLL injection.
Originally Posted by The trick
Until there is a normal example showing the problem, I won't help you.
.. can't use do...loop or for...next to find hwnd (GetWindow(hWnd, GW_HWNDNEXT)), I changed the method used "EnumWindows " to finding the handle ! i donot know why.but now can work ok~~