Bizarre hook behavior 32/64 bit - dll

I'm using a local hook (WH_KEYBOARD) with ms word (OpusApp). Well, as far as I know a 32bit app with a 32bit DLL must work only with 32bit target applications. The weird thing is that the program only works with 64bits apps!!! That is it, only with 64bits APPS! For example, it works with IE 64 but not with IE 32!
The app and dll are 32bit compiled with radstudio XE2, I confirmed the version into PE header.
In 32bit OSs, the app and dll doesn´t work.
I found no solutions on net and see no starting point to solve this weird problem.
The DLL code:
// Exported functions
extern "C" __declspec(dllexport)bool __stdcall InstallMouseHook(unsigned long, void *);
extern "C" __declspec(dllexport)bool __stdcall RemoveMouseHook();
// Callback Procedure Declaration
LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam);
// Global variables
HHOOK HookHandle;
HINSTANCE DllInstance;
typedef void (__stdcall *CALLIT)(int,WPARAM,LPARAM);
CALLIT callIt = NULL;
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
DllInstance=hinst;
return 1;
}
bool __stdcall InstallMouseHook(unsigned long pid, void *function)
{
callIt = ( CALLIT ) function;
if (function == NULL) {
ShowMessage("function is null!");
} else if (callIt == NULL) {
ShowMessage("callIt is null!");
}
HookHandle=SetWindowsHookEx(WH_KEYBOARD ,reinterpret_cast<HOOKPROC> (HookProc),DllInstance,pid);
if (HookHandle==NULL)return false;
else return true;
}
bool __stdcall RemoveMouseHook()
{
if(UnhookWindowsHookEx(HookHandle)==0)
{
return false;
}
else return true;
}
LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
{
if (code<0) {
return CallNextHookEx(HookHandle,code,wParam,lParam);
}
if (callIt != NULL) {
callIt(code,wParam,lParam);
} else {
ShowMessage("HookProc - no function to execute OR 32/64 bits problem!");
}
//Call the next hook in the chain
return CallNextHookEx(HookHandle,code,wParam,lParam);
}
The EXE calling code:
void __fastcall TfrmMouseHook::btnHookAppDllClick(TObject *Sender)
{
HWND hWindow;
unsigned long pid;
String s = "MouseHookDLL.dll";
DllHandle=LoadLibrary(s.w_str());
MOUSEHOOKFCT_2 InstHook=reinterpret_cast<MOUSEHOOKFCT_2> (GetProcAddress(DllHandle,"InstallMouseHook"));
hWindow = FindWindow(ComboBox1->Text.w_str(),NULL);
if (!hWindow) {
msg("hWindow fail");
return;
}
pid = GetWindowThreadProcessId(hWindow ,0);
if (!pid) {
msg("pid fail");
return;
}
if(!InstHook(pid, (void *) callIt )) {
msg("Unable to install hook!");
} else {
msg(" #### hook INSTALLED! ####");
}
}
CALLIT callIt(code,wParam,lParam) {
frmMouseHook->msg("hook callit: code="+IntToStr(code) +" wparam="+IntToStr(wParam)+" lparam="+IntToStr(lParam) );
}
Call IT is a function pointer to a hooker app function.
Any ideas will be very wellcome!

It is physically impossible for a 32-bit app to install a 32-bit hook DLL and have it executed in 64-bit processes. A 32-bit DLL simply cannot be injected into a 64-bit process. Period. MSDN says this in multiple places, including in the SetWindowsHookEx() documentation:
SetWindowsHookEx can be used to inject a DLL into another process. A
32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL
cannot be injected into a 32-bit process. If an application requires
the use of hooks in other processes, it is required that a 32-bit
application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit
processes, and a 64-bit application call SetWindowsHookEx to inject a
64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have
different names.
Because hooks run in the context of an application, they must match
the "bitness" of the application. If a 32-bit application installs a
global hook on 64-bit Windows, the 32-bit hook is injected into each
32-bit process (the usual security boundaries apply). In a 64-bit
process, the threads are still marked as "hooked." However, because a
32-bit application must run the hook code, the system executes the
hook in the hooking app's context; specifically, on the thread that
called SetWindowsHookEx. This means that the hooking application must
continue to pump messages or it might block the normal functioning of
the 64-bit processes.
If a 64-bit application installs a global hook on 64-bit Windows, the
64-bit hook is injected into each 64-bit process, while all 32-bit
processes use a callback to the hooking application.
The fact that you say your app and DLL do not work on 32-bit OS versions suggests your hooking code is flawed to begin with. But you have not shown enough code to diagnose that one way or the other.

What happens? Besides MSDN or anyone else says, there are some bug in XE6, compiling DLL in newer versions of IDE make this behavior disappears, in fact, the new DLL crash and hook nothing.
As Remy noted, by test I passed a function pointer to the DLL, one wrong thing to do but, when added with the wrong thing done by Embarcadero, sort of functioned.
By now, and I know people will get mad, I put both methods (the wrong and the correct hooks) in the same DLL and in my application and... get crazy... could hook into 32 and 64 bits app with only one DLL.
Don't believe? Install XE6 and try!
And Works in windows 10 as well in windows 7.

Related

DLL Code injection to third party process using QueueUserAPC

I want to inject my dll in to 64 bit application and I have tried the logic explained in the given link using QueueUserAPC. I am getting success message for every API but when I see in ProcessExplorer I am not able to see my dll in the process.
Below is my code :
bool FindProcess(PCWSTR exeName, DWORD& pid, vector<DWORD>& tids) {
auto hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return false;
pid = 0;
PROCESSENTRY32 pe = { sizeof(pe) };
if (::Process32First(hSnapshot, &pe)) {
do {
if (_wcsicmp(pe.szExeFile, exeName) == 0) {
pid = pe.th32ProcessID;
THREADENTRY32 te = { sizeof(te) };
if (::Thread32First(hSnapshot, &te)) {
do {
if (te.th32OwnerProcessID == pid) {
tids.push_back(te.th32ThreadID);
}
} while (::Thread32Next(hSnapshot, &te));
}
break;
}
} while (::Process32Next(hSnapshot, &pe));
}
::CloseHandle(hSnapshot);
return pid > 0 && !tids.empty();}
void main(){
DWORD pid;
vector<DWORD> tids;
if (FindProcess(L"DataGrid.exe", pid, tids))
{
printf("OpenProcess\n");
HANDLE hProcess = ::OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);
printf("VirtualAllocEx\n");
auto p = ::VirtualAllocEx(hProcess, nullptr, 1 << 12, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
wchar_t buffer[] = L"C:\\Users\\sbhuma\\Documents\\Visual Studio 2015\\Projects\\GalaxyHook\\Debug\\GalaxyHook.dll";
printf("WriteProcessMemory\n");
::WriteProcessMemory(hProcess, p, buffer, sizeof(buffer), nullptr);
for (const auto& tid : tids)
{
printf("OpenThread\n");
HANDLE hThread = ::OpenThread(THREAD_SET_CONTEXT, FALSE, tid);
if (hThread)
{
printf("GetProcAddress\n");
DWORD word = ::QueueUserAPC((PAPCFUNC)::GetProcAddress(GetModuleHandle(L"kernel32"), "LoadLibraryW"), hThread, (ULONG_PTR)p);
if (word)
{
printf("insdie if\n");
}
printf("End of IF\n");
}
}
printf("VirtualFreeEx\n");
::VirtualFreeEx(hProcess, p, 0, MEM_RELEASE | MEM_DECOMMIT);
}}
Any help related to inject the dll in to 64 bit application is helpful as I am new to this topic.
Regards,
Sowmya.
First of all, ensure you’re building your injector app as 64 bit.
One possible reason is you’re releasing the buffer too early. QueueUserAPC doesn’t wait; it enqueues the call and returns immediately. Can be your injector process ends running that for loop, calls VirtualFreeEx, then your target process receives the APC, tries to load your DLL but the name buffer is already released by then, so LoadLibrary fails. To verify, comment out the call to VirtualFreeEx. If your DLL will load OK, one way to fix the memory leak is use a named event, CreateEvent in injector app before any calls to QueueUserAPC(), OpenEvent, SetEvent and CloseHandle in DllMain(DLL_PROCESS_ATTACH) of the DLL you’re injecting, WaitForSingleObject in injector app before VirtualFreeEx, I recommend using a timeout for the wait, CloseHandle at the end. As a side effect, your injector app will be able to find out, and report somewhere, whether the injection was successful.
Another possible reason is your target app never enters alertable state. Not all apps use APC, there’re multiple alternative methods to implement asynchronous stuff in Windows. So, not all apps ever call these SleepEx / WaitForMultipleObjectsEx functions. Such app will never receive that APC. If that’s the case, you should use another method of DLL injection. DataGrid.exe name hints your target app is probably a GUI app. You can EnumWindows or FindWindow to find its top-level window, GetWindowThreadProcessId to get thread ID who owns that window, SetWindowsHookEx to inject your DLL into the target process.

How to find the entry point(or base address) of a process - take care of ASLR

Because of ASLR(Address space layout randomization, since Windows Vista), the base address of an exe is random, so it can't be found in PE file anymore.
In Visual C++ now the /DYNAMICBASE option is default enabled, so the base address
of an exe is random - everytime the loader loads it, it happens.
After did some research on google, I am trying to use this pattern,
But it doesn't work.
Please have a look at this simple code sample:
#include <iostream>
#include <vector>
#include <stdio.h>
#include <windows.h>
#include <psapi.h>
int main()
{
STARTUPINFOA startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
PROCESS_INFORMATION processInformation = {0};
if (CreateProcessA("UseCase01.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
{
std::vector<HMODULE> buf(128);
DWORD needed = 0;
for (;;) {
if (EnumProcessModulesEx(processInformation.hProcess, &buf[0], DWORD(buf.size()*sizeof(HMODULE)), &needed, LIST_MODULES_ALL) == FALSE) {
DWORD ec = GetLastError();
std::cout << ec << std::endl;
break;
}
else if (needed <= buf.size() * sizeof(HMODULE)) {
break;
}
else {
const size_t oldSize = buf.size();
buf.resize(oldSize * 2);
}
}
ResumeThread(processInformation.hThread);
}
}
My OS is Windows 7 64bit pro, my compiler is VS2013, this is a 32bit console program, and the UseCase01.exe is also a 32bit console program too.
EnumProcessModulesEx always fails, the error code returned by GetLastError() is 299, MSDN says what about this error code: ERROR_PARTIAL_COPY, "Only part of a ReadProcessMemory or WriteProcessMemory request was completed."
About this error code, on the EnumProcessModules's page of MSDN, "If this function is called from a 32-bit application running on WOW64, it can only enumerate the modules of a 32-bit process. If the process is a 64-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299)."
But I am sure my program is 32bit, And, I tested on 64bit program, it fails with error 299 too, so it doesn't make sence.
"The handle returned by the CreateProcess function has PROCESS_ALL_ACCESS access to the process object." - from MSDN, so it can't be a access rights problem ?
Then I try to use CreateToolhelp32Snapshot, it fails with error code 299 too, both 32bit and 64bit.
I just can't figure it out.
My goal is find the entry point of the sub-process in a safe way, whatever it's 32bit or 64bit process.
I found this is the "deepest" answer about this question: http://winprogger.com/getmodulefilenameex-enumprocessmodulesex-failures-in-wow64/
Unfortunately, 64bit program will fails too, not only for Wow64, so it doesn't make sence.
If this is infeasible, what is the good way (find base address or entry point of a suspended sub-process)?
You are creating the process suspended. While the key kernel data structures will be created, no modules will be loaded (that would involve executing code in module entry points (dllmain)).
Thus the error makes sense: the data structures to track modules loaded will be empty, and quite possibly not allocated at all.
Put some wait it will help you it looks currently resource is not available.
On all Windows operating systems (32/64bit):
DWORD ImageBaseAddress = ((LPDWORD)PEB)[2]

urldownloadtofile OR InternetOpenUrl not working from DLL

I am trying to use UrlDownloadToFile OR InternetOpenUrl to visit some link on the Internet from an DLL file. While it works on an .exe file, but it didn't work from a DLL file, and even no any error information. It just failed without any information.
Anyone could give me any help? Thanks in advance.
My code are as below:
extern "C" __declspec(dllexport) int __stdcall Hello()
{
HINTERNET hInt=NULL, hUrl=NULL;
hInt = InternetOpenA("Test Agent", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
hUrl = InternetOpenUrlA(hInt, "http://www.google.com.au", NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE, 0);
if (hUrl)
{
InternetCloseHandle(hUrl);
}
InternetCloseHandle(hInt);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Hello();
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
It failed at:
hUrl = InternetOpenUrlA(hInt, "http://www.google.com.au", NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE, 0);
Or:
typedef HRESULT (__stdcall * lpURLDownloadToFile) (LPUNKNOWN pCaller, LPCTSTR szURL, LPCTSTR szFileName, DWORD dwReserved, LPBINDSTATUSCALLBACK lpfnCB);
extern "C" __declspec(dllexport) int __stdcall Hello()
{
HMODULE hModule = LoadLibraryW(L"urlmon.dll");
lpURLDownloadToFile urlD = (lpURLDownloadToFile)GetProcAddress( hModule, "URLDownloadToFileW" );
HRESULT aa = urlD(NULL, L"http://www.google.com.au", L"C:\\Test\\a.html", 0, NULL);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Hello();
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
It failed at:
HRESULT aa = urlD(NULL, L"http://www.google.com.au", L"C:\\Test\\a.html", 0, NULL);
Update:
If I insert a line like "MessageBox" just above where it fails, the MessageBox will be displayed successfully.
If I insert a line like "MessageBox" just after where it fails, the MessageBox will not be displayed. And there is no any error code returned if I tried to display "hUrl" or "aa".
Don't do that in DllMain. See DllMain entry point
The entry-point function should perform only simple initialization or
termination tasks. It must not call the LoadLibrary or LoadLibraryEx
function (or a function that calls these functions), because this may
create dependency loops in the DLL load order. This can result in a
DLL being used before the system has executed its initialization code.
EDIT, as you want to inject the Dll and run code in it.
One way to make an injected Dll to start executing code, without relying on DllMain is as follow:
Use a message hook, limited to one thread.
Find a HWND belonging to the process you want to inject. For Internet Explorer, you may enumerate the Top Level Windows, using EnumWindows A main IE Windows has a class IEframe. Use EnumChildWindows to find a window of class Internet_Explorer Server. Use GetWindowThreadProcessId to get the associated TID (Thread Identifier).
Use SetWindowsHookEx to install a thread hook. You may choose a WH_CALLWNDPROC
or a WH_GETMESSAGE hook. Pass the TID obtained in 1. Your DLL is injected, and is processing messages.
Use PostMessage or SendMessage or PostThreadMessage, depending on the hook type you choose in 2, with a registered message. See RegisterWindowMessage
In your hook function, filter for the registered message (obtain it's value in your DllMain and store it in a global variable) and when this message is received, call your custom code.
Warning: this technique is well suited for short living code, you are in a hook function. That's maybe not the place for downloading from the Internet.
Another way is to create a thread in DllMain, using _beginthreadex
In the thread, you may have a classic RegisterClass / CreateWindow / GetMessage/ DispatchMessage sequence, and your EXE will be able to Send/Post messages to your Dll.
Warning: depending on how you injected the Dll, you must be very carreful about premature unloading of your Dll. If the thread still runs, there may be crashes. Being clean and stable with theses things is not easy. But, if you are just playing/experimenting, don't bother and just LoadLibrary (not in DllMain) you own library a second time, it will stay here forever.
You can mix the two techniques, that is: use a thread message hook to inject the Dll and start a thread in the hook function.

SetWindowsHookEx returns with "Invalid window handle" since moving to .net 4.0

Since moving to .net 4.0 from 2.0, I cannot run successfully the SetWindowsHookEx function. It always ends with the Win32 error number 1400: "Invalid window handle".
This is the pinvoke signature:
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, int hModule, int dwThreadId);
This is the call:
SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, iModule, 0);
It worked before. Why should it return with an "Invalid window handle" error anyway ?
btw: on windows 7 it works, but only if I set iModule = 0. on XP it doesn't work anyhow.
Problem solved:
The problem was the iModule. I assigned it this way:
int iModule = System.Runtime.InteropServices.Marshal.GetHINSTANCE(
System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0])
).ToInt32();
And the right way to do that, is apparently:
int iModule = System.Diagnostics.Process.GetCurrentProcess().MainModule.BaseAddress.ToInt32();
But I'll be glad to know the reason for that. Logically, the GetModules()[0] gives the dll file itself where the callback function resides, while GetCurrentProcess().MainModule.BaseAddress returns the main module (dll file ?), that may be different from the dll that holds the callback function.
So how come it actually works "the other way around" - according to my understanding ? and how come it worked until I changed the .net version ?

.NET CF - MSMQ ActivateDevice() Crash

I have a .NET 3.5 Compact Framework application that uses MSMQ.
We are running this application on an Intermec CN3, Windows Mobile 5.0 device.
However, when our application first tries to active the MSMQ service with ActivateDevice (pinvoke), the application crashes and we get the error report message:
A problem has occuurred with myApp.exe
Please tell Microsoft about this problem, at not cost to you. ect..
What we have done is this:
Hard Reset the Device
Install NETCFv35.wm.armv4i.cab
Install msmq.arm.CAB
*Run a CF console app that sets up MSMQ and the registry
Soft reset the PDA
*Run our application which calls ActivateDevice() on startup
After doing a soft reset, the first time that ActivateDevice() is called, the application crashes.
However, now that we have called ActivateDevice(), MSMQ services are working on the device atleast until it is soft reset again.
Also, any calls to ActivateDevice() will not crash the application.
The console app that we run after a hard reset is basically this:
class InstallRegister
{
public void Main()
{
RunMsmqAdmin("install");
RunMsmqAdmin("register install");
RunMsmqAdmin("register");
SetQuotaValueRegistry("MachineQuota");
SetQuotaValueRegistry("DefaultLocalQuota");
SetQuotaValueRegistry("DefaultQuota");
RunMsmqAdmin("enable binary");
RunMsmqAdmin("enable srmp");
RunMsmqAdmin("start");
RegFlushKey(0x80000002);
}
private void SetQuotaValueRegistry(string quotaValueName)
{
Microsoft.Win32.Registry.SetValue(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSMQ\\SimpleClient\\"
, quotaValueName
, 100000);
}
private void RunMsmqAdmin(string command)
{
using (Process _process = new Process())
{
_process.StartInfo.FileName = #"\windows\msmqadm.exe";
_process.StartInfo.Arguments = command;
_process.StartInfo.UseShellExecute = true;
_process.Start();
_process.WaitForExit();
}
}
[System.Runtime.InteropServices.DllImport("CoreDll.dll", EntryPoint = "RegFlushKey", SetLastError = true)]
private static extern uint RegFlushKey(uint hKey);
}
Our applications call to ActivateDevice() is basically this:
class ActivateMSMQ
{
public void Active()
{
var handle = ActivateDevice("Drivers\\BuiltIn\\MSMQD", 0);
CloseHandle(handle);
}
[System.Runtime.InteropServices.DllImport("CoreDll.dll", SetLastError = true)]
private static extern IntPtr ActivateDevice(string lpszDevKey, Int32 dwClientInfo);
[System.Runtime.InteropServices.DllImport("CoreDll.dll", SetLastError = true)]
private extern static Int32 CloseHandle(IntPtr hProcess);
}
ActivateDevice() still causes our app the crash whenever the device is soft reset.
Has anyone else experienced this with MSMQ on the compact framework?
Yes this problem occurs. the quick and easy fix for this is to put the code into a separate executable, then on the start of you app launch this process and wait for completion. The process will terminate due to the crash but will return with your calling app still intact. Then just make sure the executable is deployed in your cab so you app can call it.