DLL_PROCESS_DETACH not called C++ - dll-injection

Sup!
i make a simple script for attaching/detaching but if i press F11, the DLL gets killed but not in the "normal way", DLL_PROCES_DETACH is not called
what can be the problem?
#include <Windows.h>
#include <thread>
HMODULE hMod = nullptr;
bool bDebugMode = true;
bool bLeave = false;
void Setup(void);
void Setup()
{
while (true)
{
if (GetAsyncKeyState(VK_F11) & 1)
{
std::this_thread::sleep_for(std::chrono::milliseconds(200));
FreeLibraryAndExitThread(hMod, 1);
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
hMod = hModule;
DisableThreadLibraryCalls(hModule);
if(bDebugMode)
MessageBox(NULL, "Attach", "Attached", MB_OK);
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Setup, 0, 0, 0); break;
case DLL_THREAD_DETACH:
Beep(500, 100);
if(bDebugMode)
MessageBox(NULL, "Detach", "Detach called!", MB_OK); break;
}
return true;
}
any help would be appreciated!

Well your code is fine, except there is no case DLL_PROCESS_DETACH inside of your switch statement. Sometimes it just takes another pair of eyes to see the mistake.
EDIT: You should be able to switch the DLL_THREAD_DETACH with DLL_PROCESS_DETACH and everything will work fine.

Related

Why does my screen starts blinking when I toggle the full screen state?

I'm trying to implement full screen support on my Direct3D11 application, but I've been having a issue with this. I'm using the ALT+ENTER key combination that makes the IDXGISwapChain change the target window to full screen and back. But when I go into full screen my back buffer starts blinking between the color that I have set on the call to ID3D11DeviceContext::ClearRenderTargetView to black.
I also have code in the WinProc function of my window, that when it receives the WM_SIZE message, this code is executed.
If I don't use this code to resize the buffers, the blinking doesn't happen for some reason.
If I call ID3D11DeviceContext::ClearRenderTargetView once after creating the new swap chain, and again after calling IDXGISwapChain::Present, the blinking also doesn't happen.
It's a bit confusing, but I have a theory that maybe, when I go to full screen mode and call IDXGISwapChain::ResizeBuffers it somehow makes my swap chain have more than one buffer, and when I call IDXGISwapChain::Present it rotates to the next buffer, which is on the default color black.
Note that I have also tried to call IDXGISwapChain::SetFullscreenState, but the issue persists.
My code is too big to paste here, so I took the code from this tutorial and changed it a bit to show the behaviour I'm describing:
#include <windows.h>
#include <d3d11.h>
#pragma comment (lib, "d3d11.lib")
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// global declarations
IDXGISwapChain* swapchain;
ID3D11Device* dev;
ID3D11DeviceContext* devcon;
ID3D11RenderTargetView* backbuffer;
void InitD3D(HWND hWnd);
void RenderFrame(void);
void CleanD3D(void);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int main()
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandle(nullptr);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);
RECT wr = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
hWnd = CreateWindowEx(NULL,
L"WindowClass",
L"Our First Direct3D Program",
WS_OVERLAPPEDWINDOW,
300,
300,
wr.right - wr.left,
wr.bottom - wr.top,
NULL,
NULL,
GetModuleHandle(nullptr),
NULL);
ShowWindow(hWnd, SW_SHOW);
InitD3D(hWnd);
MSG msg;
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
RenderFrame();
}
CleanD3D();
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
case WM_SIZE: {
if (swapchain)
{
devcon->OMSetRenderTargets(0, 0, 0);
backbuffer->Release();
HRESULT hr;
hr = swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
ID3D11Texture2D* pBuffer;
hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D),
(void**)&pBuffer);
hr = dev->CreateRenderTargetView(pBuffer, NULL,
&backbuffer);
pBuffer->Release();
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
float fColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
devcon->ClearRenderTargetView(backbuffer, fColor);
DXGI_SWAP_CHAIN_DESC Desc;
ZeroMemory(&Desc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapchain->GetDesc(&Desc);
D3D11_VIEWPORT vp;
vp.Width = Desc.BufferDesc.Width;
vp.Height = Desc.BufferDesc.Height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
devcon->RSSetViewports(1, &vp);
}
return 1;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void InitD3D(HWND hWnd)
{
DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
scd.BufferCount = 1;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferDesc.Width = SCREEN_WIDTH;
scd.BufferDesc.Height = SCREEN_HEIGHT;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = hWnd;
scd.SampleDesc.Count = 1;
scd.Windowed = TRUE;
scd.Flags = 0;
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);
ID3D11Texture2D* pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
float fColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
devcon->ClearRenderTargetView(backbuffer, fColor);
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = SCREEN_WIDTH;
viewport.Height = SCREEN_HEIGHT;
devcon->RSSetViewports(1, &viewport);
}
void RenderFrame(void)
{
swapchain->Present(1, 0);
}
void CleanD3D(void)
{
swapchain->SetFullscreenState(FALSE, NULL);
swapchain->Release();
backbuffer->Release();
dev->Release();
devcon->Release();
After messing a bit with the code, I've noticed that when the SampleDesc::Count variable from the DXGI_SWAP_CHAIN_DESC is not equal to 1, the blinking also doesn't happen.

How to get type of object when using ole automation (C++)

I'm using the autowrap function to interact with VBA and now I get the control using item method as below.
VARIANT result;
VariantInit(&result);
VARIANT x;
x.vt = VT_INT;
x.intVal = index;
wchar_t method[] = L"Item";
hr = AutoWrap(DISPATCH_METHOD, &result, pControls, method,1,x);
pObject = result.pdispVal;
I can get the name of the control item using this code below:
VARIANT result;
VariantInit(&result);
wchar_t method[] = L"Name";
hr = AutoWrap(DISPATCH_PROPERTYGET, &result, pObject, method, 0);
QString name=QString::fromWCharArray(result.bstrVal);
But I can't seem to find a property to get the type of object (textbox, commandbutton and etc). In VBA, there is a TypeName() function to get the type. So how can I actually do it in OLE automation autowrap function? Thanks.
Here is an example... could be optimized with a function to check the result and throw/catch an exception, but it is what it is.
#include <windows.h>
#include <atlbase.h>
#include <comdef.h>
#include <stdio.h>
int main(int argc, TCHAR* argv[])
{
class CComInit
{
public:
CComInit()
{
CoInitialize(NULL);
}
~CComInit()
{
CoUninitialize();
}
} _init;
IDispatchPtr lpDisp;
HRESULT hr = lpDisp.CreateInstance(L"Scripting.FileSystemObject");
if (FAILED(hr))
{
_com_error err(hr);
printf("Error %s\n", err.ErrorMessage());
return 0;
}
ITypeInfoPtr lpTypeInfo;
hr = lpDisp->GetTypeInfo(0, 0, &lpTypeInfo);
if (FAILED(hr))
{
_com_error err(hr);
printf("Error %s\n", err.ErrorMessage());
return 0;
}
CComBSTR ccbName, ccbDocString;
hr = lpTypeInfo->GetDocumentation(-1, &ccbName, &ccbDocString, NULL, NULL) ;
if (FAILED(hr))
{
_com_error err(hr);
printf("Error %s\n", err.ErrorMessage());
return 0;
}
printf("Type name: %S\n", ccbName.m_str);
printf("Doc: %S\n", ccbDocString.m_str);
return 0;
}

Visual-C++ Win32 C++ Application. How do I print variables to the main screen?

I have tried C++11 methods and C methods to convert the string before printing and they either: Returned a string of the same characters or didn't print anything at all. I just wanted to know 3 things really: Is there a fault in the online tutorials and examples? Is there a fault in my interpretation and implementation of the code? What could I do differently to get this working?
// Yu-Gi-Oh! LP Calculator.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Yu-Gi-Oh! LP Calculator.h"
#define MAX_LOADSTRING 100
#define LP UINT
#define ID CHAR
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Global Life Point Variables
struct Player {
LP Lp;
ID Name[MAX_LOADSTRING];
};
struct Player1, Player2, Player3, Player4;
// Forward declarations of functions included in this code module:
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TEMP: Remove these initializations when preferences are implemented.
Player1.Lp = 8000;
Player2.Lp = 8000;
Player3.Lp = 8000;
Player4.Lp = 8000;
LoadStringA(hInstance, (UINT)"John\0", Player1.Name, MAX_LOADSTRING);
LoadStringA(hInstance, (UINT)"Phil\0", Player2.Name, MAX_LOADSTRING);
LoadStringA(hInstance, NULL, Player3.Name, MAX_LOADSTRING);
LoadStringA(hInstance, NULL, Player4.Name, MAX_LOADSTRING);
// END TEMP
// TODO: Place code here.
// TODO: Load preferences file.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_YUGIOHLPCALCULATOR, szWindowClass, MAX_LOADSTRING);
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_YUGIOHLPCALCULATOR));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_YUGIOHLPCALCULATOR);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_YUGIOHLPCALCULATOR));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
GetClientRect(hWnd, &rect);
CHAR b[] = { NULL };
sprintf((char* const)&b, "%s", Player1.Name);
DrawTextA(hdc, b, ARRAYSIZE(b), &rect, DT_SINGLELINE | DT_CENTER | DT_TOP);
//TextOutA(hdc, rect.left, rect.top, s, ARRAYSIZE(Player1.Name));
SelectClipPath(hdc, RGN_AND);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
By changing:
#define ID CHAR
to:
#define ID LPCSTR
and changing:
ID Name[MAX_LOADSTRING];
to:
ID Name;
I made Player1.Name compatible with the type of the 2nd parameter of the DrawTextA function.
I then changed the 3rd parameter to -1 instead of using ARRAYSIZE(). This means that the function checks the size of the string itself? So the function is called like this:
DrawTextA(hdc, Player1.Name, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_TOP);
All I needed to do then was Initialize the string with my values instead of using LoadStringA so I changed:
LoadStringA(hInstance, (UINT)"John\0", Player1.Name, MAX_LOADSTRING);
to:
Player1.Name = "John";

DllMain not being called from injected dll

I am attempting to inject a dll into an existing process using the LoadLibrary and CreateRemoteThread approach. All of my code is working beautifully except for the fact that DllMain is not being called for some reason.
I've wracked my brains and done as much internet research as I can but none of the suggestions have helped.
When I statically load the dll into a sample project it works beautifully.
When I dynamically load the dll into a sample project using LoadLibrary, it works beautifully.
The only time that DllMain is not called is when I'm trying to inject it into a process using the LoadLibrary and CreateRemoteThread approach. I'm at my wits end!
I have verified that the dll is loaded into the notepad.exe process from the injector because the SimpleDLL.dll file is locked and cannot be deleted or overwritten until I close notepad.exe.
Fyi, my ide is Microsoft Visual Studio 2010 Ultimate.
// SimpleDLL.h
#pragma once
#include "Stdafx.h"
#ifdef COMPILE_MYLIBRARY
#define MYLIBRARY_EXPORT __declspec(dllexport)
#else
#define MYLIBRARY_EXPORT __declspec(dllimport)
#endif
.
//SimpleDLL.cpp
#include "Stdafx.h"
#include "SimpleDll.h"
extern "C" int __stdcall DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) {
printf("SimpleDll: DllMain called.\n");
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
printf("SimpleDll: DLL_PROCESS_ATTACH.\n");
break;
case DLL_PROCESS_DETACH:
printf("SimpleDll: DLL_PROCESS_DETACH.\n");
break;
case DLL_THREAD_ATTACH:
printf("SimpleDll: DLL_THREAD_ATTACH.\n");
break;
case DLL_THREAD_DETACH:
printf("SimpleDll: DLL_THREAD_DETACH.\n");
break;
}
return TRUE;
};
SimpleDLLCaller.cpp - This runs correctly and prints out the messages from DllMain. This is a project I built to verify that the dll is constructed correctly. From the output that I can see, it appears to be operating correctly when loaded in this way.
// SimpleDLLCaller.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
LoadLibraryA( "C:\\SimpleDll.dll" );
_getch();
return 0;
}
Output from SimpleDllCaller:
SimpleDll: DllMain called.
SimpleDll: DLL_PROCESS_ATTACH.
Simple Injector.cpp - This is a separate project from SimpleDLLCaller and compiles/runs successfully without warnings (as long as notepad.exe is already running) but no messages from DllMain are displayed.
// Simple Injector.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <conio.h>
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
BOOL Inject(DWORD pID, const char * dll_name )
{
HANDLE targetProcess, createdThread;
//HMODULE hLib;
char buf[50] = {0};
LPVOID myRemoteString, LoadLibAddy;
if( ! pID )
{
return FALSE;
}
targetProcess = OpenProcess( CREATE_THREAD_ACCESS, FALSE, pID );
if( ! targetProcess )
{
sprintf_s(buf, "OpenProcess() failed: %d", GetLastError());
MessageBox(NULL, buf, "Loader", MB_OK);
printf(buf);
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if( ! LoadLibAddy )
{
printf( "ERROR: Problems with GetProcAddress. Error code: %d\n", GetLastError() );
return false;
}
// Allocate space in the process for the dll
myRemoteString = (LPVOID)VirtualAllocEx( targetProcess, NULL, strlen(dll_name), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if( ! myRemoteString )
{
printf( "ERROR: Problems with VirtualAllocEx. Error code: %d\n", GetLastError() );
return false;
}
// Write the string name of the dll in the memory allocated
if( ! WriteProcessMemory( targetProcess, (LPVOID)myRemoteString, dll_name, strlen(dll_name), NULL) )
{
printf( "ERROR: Problems with WriteProcessMemory. Error code: %d\n", GetLastError() );
return false;
}
// Load the dll
createdThread = CreateRemoteThread( targetProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)myRemoteString, NULL, NULL);
if( ! createdThread )
{
printf( "ERROR: Problems with CreateRemoteThread. Error code: %d\n", GetLastError() );
return false;
}
WaitForSingleObject(createdThread, INFINITE);
// Free the memory that is not being using anymore.
if( myRemoteString != NULL ) VirtualFreeEx( targetProcess, myRemoteString, 0, MEM_RELEASE );
if( createdThread != NULL ) CloseHandle( createdThread );
if( targetProcess != NULL ) CloseHandle( targetProcess );
//VirtualFreeEx(hProcess , (LPVOID)Memory , 0, MEM_RELEASE);
return true;
}
DWORD GetTargetThreadIDFromProcName(const char *ProcName)
{
PROCESSENTRY32 pe;
HANDLE thSnapShot;
BOOL retval, ProcFound = false;
thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(thSnapShot == INVALID_HANDLE_VALUE)
{
//MessageBox(NULL, "Error: Unable <strong class="highlight">to</strong> create toolhelp snapshot!", "2MLoader", MB_OK);
printf("Error: Unable to create toolhelp snapshot!");
return false;
}
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapShot, &pe);
while(retval)
{
if( !strcmp(pe.szExeFile, ProcName) )
{
return pe.th32ProcessID;
}
retval = Process32Next(thSnapShot, &pe);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
// Retrieve process ID
DWORD pID = GetTargetThreadIDFromProcName("notepad.exe");
if( !pID )
{
printf( "ERROR: Could not find any process for notepad.exe.\n");
_getch();
return 0;
}
// Get the dll's full path name
char buf[MAX_PATH] = {0};
// GetFullPathName("..\\SimpleDLL.dll", MAX_PATH, buf, NULL);
sprintf_s(buf, "C:\\SimpleDLL.dll");
printf( "Dll path = %s\n", buf );
// Inject our main dll
if(!Inject(pID, buf))
{
printf("Dll not loaded.");
}
else
{
printf("Dll loaded.");
}
_getch();
return 0;
}
Output from Simple Injector:
Dll path = C:\SimpleDLL.dll
Dll loaded.
Please tell me what I'm doing wrong here. Any feedback is welcome.
Your DLL may be correctly Loaded. Don't expect your printf to do do anything. If you want a proof, write your message in a text file, or use MessageBox, or use Process Explorer.

Global hook take effects when the API is called for the second time

All
I have implemented a global Windows hook to hook the API MessageBox(), the hook is implemented in a dll, when I setup the windows hook in a win32 console application (with the dll loaded) and call MessageBox(), the API is successfully hooked. For brevity, I name this win32 application EXE1.
Since I set up a global hook, I also want the calls to MessageBox() by other applications also be hooked. Therefore, I run another win32 console application -- EXE2 (with EXE1 running at the same time), which calls MessageBox() for three times. However, the first call is not hooked. I don't know why. (The code is in ansi format.) The codes are as follows:
-----------------------dll--------------------------------------------
#pragma once
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
//for the getaddrinfo test
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32")
#include <windows.h>
#include <stdio.h>
#include "mhook.h"
//=========================================================================
// Define _MessageBox so we can dynamically bind to the function
typedef int (WINAPI* _MessageBox) (HWND, LPCTSTR, LPCTSTR, UINT);
//=========================================================================
// Get the current (original) address to the functions to be hooked
//
_MessageBox TrueMessageBox = (_MessageBox)GetProcAddress(GetModuleHandle(L"user32"), "MessageBoxW");
//=========================================================================
// This is the function that will replace MessageBox once the hook
// is in place
MMRESULT WINAPI HookMessageBoxW(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType){
printf("***** Call to MessageBox\n");
lpText = L"hooked MessageBox";
// Call the original waveInOpen function
MMRESULT nResult = TrueMessageBox(hWnd, lpText, lpCaption, uType);
return nResult;
}
///////////////////////////////////////////////////////////////////////////
#pragma comment(linker, "/SECTION:YCIShared,RWS")
#pragma data_seg("YCIShared")
HHOOK g_hHook = NULL;
#pragma data_seg()
HMODULE hInstance = 0;
static LRESULT WINAPI GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{ printf("=======\n");
//Mhook_SetHook((PVOID*)&TrueMessageBox, HookMessageBoxW);
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}
BOOL WINAPI SetSysHook(BOOL bInstall, DWORD dwThreadId)
{
BOOL bOk;
if(bInstall)
{
g_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,
hInstance, dwThreadId);
bOk = (g_hHook != NULL);
}
else
{
bOk = ::UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
return bOk;
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hInstance = (HINSTANCE) hModule;
printf("dll loaded!============================\n");
if(Mhook_SetHook((PVOID*)&TrueMessageBox, HookMessageBoxW)) //hook
printf("MessageBox Hook Succeeded!\n");
else
printf("MessageBox Hook Failed");
break;
case DLL_PROCESS_DETACH:
Mhook_Unhook((PVOID*)&TrueMessageBox);
break;
}
return TRUE;
}
-------------------------------end of dll---------------------------------------------
You cannot build this dll because it calls a self-implemented function Mhook_SetHook() and Mhook_Unhook(), which are from mhook. The DLL file is named as mhook-2.3-dll.dll.
------------------------------EXE1---------------------------------------------------
#pragma once
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "mhook-2.3-dll.lib")
extern "C" _declspec(dllimport) BOOL WINAPI SetSysHook(BOOL bInstall, DWORD dwThreadId);
int wmain(int argc, WCHAR* argv[])
{
//HMODULE hModule = ::LoadLibrary(L"mhook-2.3-dll.dll");
SetSysHook(TRUE, 0);
MessageBoxW(NULL, (LPCTSTR)L"MessageBox", NULL, MB_OK); //hooked
SetSysHook(FALSE, 0);
return 0;
}
--------------------------------end of EXE1-----------------------------------------
--------------------------------EXE2------------------------------------------------
#include
#include
int main(){
MessageBox(NULL, (LPCTSTR)L"MessageBox1", NULL, MB_OK); //not hooked
MessageBox(NULL, (LPCTSTR)L"MessageBox2", NULL, MB_OK); //hooked
MessageBox(NULL, (LPCTSTR)L"MessageBox3", NULL, MB_OK); //hooked
return 0;
}
-------------------------------end of EXE2------------------------------------------