掃雷遊戲外掛實例。
實現功能:
1再菜單中添加自動完成菜單。
2顯示鼠標當前位置是否爲雷。
源代碼分爲兩部分。
1app部分
main.h
#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#define WM_MYHOOK (WM_APP +1024)
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button2;
TButton *Button3;
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
private: // User declarations
HINSTANCE hDLL;
HWND hHookedWindow;
unsigned long MineHeight; //雷區高度起始地址
unsigned long MineWidth; //雷區?度起始地址
unsigned long MineStartAddress; //雷區內容起始地址,依次是0x01005361+高*32+?
void __fastcall WMMYHOOK(TMessage& Message);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_MYHOOK, TMessage, WMMYHOOK);
END_MESSAGE_MAP(TForm);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
main.cpp
#include <vcl.h>
#pragma hdrstop
#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
typedef int (WINAPI* sthndl)(HWND,HWND);
sthndl SetHandle;
typedef int (WINAPI* unsub)();
unsub UnSubClass;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
hDLL = NULL;
MineHeight = 0x01005338;
MineWidth = 0x01005334;
MineStartAddress = 0x01005361;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
hDLL=LoadLibrary((LPCTSTR)"ShaoLeiWaiGua.dll");
if(hDLL==NULL){
exit(1);
}
hHookedWindow = FindWindow(NULL,"マインスイーパ");
SetHandle = (sthndl)GetProcAddress(hDLL, "SetHandle");
UnSubClass = (unsub)GetProcAddress(hDLL, "UnSubclass");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
hHookedWindow = FindWindow(NULL,"マインスイーパ");
if(hHookedWindow == NULL){
hHookedWindow = FindWindow(NULL,"Minesweeper");
}
if(hHookedWindow == NULL){
MessageBox(0,"Could Not find a running instance of Mymine. Please Start Notepad and try again","Error",0);
return;
}
HMENU hAppMenu;
hAppMenu=GetMenu(hHookedWindow);
AppendMenu(GetSubMenu(hAppMenu,1),MF_STRING,125,"Auto Complete");
SetHandle(hHookedWindow,this->Handle);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
UnSubClass();
FreeLibrary(hDLL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WMMYHOOK(TMessage& Message)
{
unsigned long MineID;
GetWindowThreadProcessId(hHookedWindow,&MineID);
HANDLE Mine = OpenProcess(PROCESS_VM_READ,true,MineID);
unsigned long nSize=1;
unsigned long lpNumberOfByteRead;
PBYTE lpBuffer = StrAlloc(nSize);
ZeroMemory(lpBuffer,nSize);
int mWidth,mHeight;
if(ReadProcessMemory(Mine,(LPCVOID)MineWidth,(LPVOID)lpBuffer,nSize,&lpNumberOfByteRead))
{
mWidth=*(unsigned long *)lpBuffer;
}
if(ReadProcessMemory(Mine,(LPCVOID)MineHeight,(LPVOID)lpBuffer,nSize,&lpNumberOfByteRead))
{
mHeight=*(unsigned long *)lpBuffer;
}
int yOffSet=60;
int xOffSet=20;
int row;
int col;
for(row=0;row<=mHeight;row++)
{
for(col=0;col<=mWidth;col++)
{
if(ReadProcessMemory(Mine,(LPCVOID)(MineStartAddress+row*32+col),(LPVOID)lpBuffer,nSize,&lpNumberOfByteRead))
{
if(*(unsigned long *)lpBuffer!=0x8F)
{
SendMessage(hHookedWindow,WM_LBUTTONDOWN,0,(LPARAM)MAKELPARAM(xOffSet+16*col,yOffSet+16*row));
SendMessage(hHookedWindow,WM_LBUTTONUP,0,(LPARAM)MAKELPARAM(xOffSet+16*col,yOffSet+16*row));
SendMessage(hHookedWindow,WM_RBUTTONDOWN,0,(LPARAM)MAKELPARAM(xOffSet+16*col,yOffSet+16*row));
SendMessage(hHookedWindow,WM_RBUTTONUP,0,(LPARAM)MAKELPARAM(xOffSet+16*col,yOffSet+16*row));
SendMessage(hHookedWindow,WM_RBUTTONDOWN,0,(LPARAM)MAKELPARAM(xOffSet+16*col,yOffSet+16*row));
SendMessage(hHookedWindow,WM_RBUTTONUP,0,(LPARAM)MAKELPARAM(xOffSet+16*col,yOffSet+16*row));
}
else
{
SendMessage(hHookedWindow,WM_RBUTTONDOWN,0,(LPARAM)MAKELPARAM(xOffSet+16*col,yOffSet+16*row));
SendMessage(hHookedWindow,WM_RBUTTONUP,0,(LPARAM)MAKELPARAM(xOffSet+16*col,yOffSet+16*row));
}
}
}
}
StrDispose(lpBuffer);
CloseHandle(hHookedWindow);
}
2dll 部分
#include <vcl.h>
#include <windows.h>
#include <iostream.h>
#include <tlhelp32.h>
#pragma hdrstop
//---------------------------------------------------------------------------
// Important note about DLL memory management when your DLL uses the
// static version of the RunTime Library:
//
// If your DLL exports any functions that pass String objects (or structs/
// classes containing nested Strings) as parameter or function results,
// you will need to add the library MEMMGR.LIB to both the DLL project and
// any other projects that use the DLL. You will also need to use MEMMGR.LIB
// if any other projects which use the DLL will be performing new or delete
// operations on any non-TObject-derived classes which are exported from the
// DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
// EXE's to use the BORLNDMM.DLL as their memory manager. In these cases,
// the file BORLNDMM.DLL should be deployed along with your DLL.
//
// To avoid using BORLNDMM.DLL, pass string information using "char *" or
// ShortString parameters.
//
// If your DLL uses the dynamic version of the RTL, you do not need to
// explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------
#pragma argsused
extern "C" __declspec(dllexport) int WINAPI SetHandle(HWND,HWND);
extern "C" __declspec(dllexport) int WINAPI UnSubclass();
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK CBTProc(int nCode,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam);
HANDLE MapGlobalData(const AnsiString MapName, int Size, LPVOID &P);
void ReleaseGlobalData(HANDLE handle, void* &Ptr);
typedef struct {
HWND hTarget;
HWND hApp;
HINSTANCE hInstance;
long OldWndHndl;
BOOL blnsubclassed;
HHOOK hWinHook;
HHOOK hMouseHook;
} TGlobalData, *PGlobalData;
const char* GLOBAL_DATA_MAPNAME = "HOOK_GLOBAL_DATA";
//---------------------------------------------------------------------------
PGlobalData g_Data;
HANDLE MapHandle;
THintWindow *ht;
unsigned long MineHeight = 0x01005338;
unsigned long MineWidth = 0x01005334;
unsigned long MineStartAddress = 0x01005361;
//---------------------------------------------------------------------------
//Window Procedures of the subclassed windows
LRESULT CALLBACK WindowProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
if(g_Data->hTarget == hwnd){
long result;
if(uMsg==273){ //Message Implying Menu Clicks
if(HIWORD(wParam)==0 && LOWORD(wParam) == 125){
result=SendNotifyMessage(g_Data->hApp,WM_APP +1024,(WPARAM)(LOWORD(wParam)),(LPARAM)uMsg);// Send the message to the vb app
}
}
if(uMsg==WM_MOUSEMOVE){
SendNotifyMessage(g_Data->hApp,WM_APP +1025,(WPARAM)(LOWORD(wParam)),(LPARAM)uMsg);// Send the message to the vb app
}
}
return CallWindowProc((WNDPROC)(g_Data->OldWndHndl),hwnd,uMsg,wParam,lParam);
}//End Procedure
//---------------------------------------------------------------------------
// Function to set the original window procedure of each subclassed window
int WINAPI UnSubclass()
{
if( (int)g_Data->hTarget > 1 ){
SetWindowLong(g_Data->hTarget,GWL_WNDPROC,g_Data->OldWndHndl); //Set back the old window procedure
}
return 1;
}//End UnSubclass function
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
MapHandle = MapGlobalData(GLOBAL_DATA_MAPNAME, sizeof(TGlobalData), Pointer(g_Data));
g_Data->hInstance = hinst;
return 1;
}
//---------------------------------------------------------------------------
// Get the handles of the Targetwindow and of the Our application
int WINAPI SetHandle(HWND HandleofTarget ,HWND HandleofApp)
{
g_Data->hTarget=HandleofTarget;
g_Data->hApp=HandleofApp;
g_Data->hWinHook=SetWindowsHookEx(WH_CBT,(HOOKPROC)CBTProc,g_Data->hInstance,GetWindowThreadProcessId(g_Data->hTarget,NULL));
g_Data->hMouseHook=SetWindowsHookEx(WH_MOUSE ,(HOOKPROC)MouseProc,g_Data->hInstance,GetWindowThreadProcessId(g_Data->hTarget,NULL));
return 1;
}//End this function
//----------------------------------------------------------------------------------------------------
//The CBT hook Proc(Computer Based Training Hook)
LRESULT CALLBACK CBTProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if (nCode==HCBT_ACTIVATE){ //Called when the application window is activated
if((HWND)(wParam)==g_Data->hTarget){ //check if the window activated is Our Targer App
if (g_Data->blnsubclassed==FALSE){
if(((int)g_Data->hTarget)>1){
g_Data->OldWndHndl=SetWindowLong(g_Data->hTarget,GWL_WNDPROC,(long)WindowProc); //Subclass !!!!
}
g_Data->blnsubclassed=TRUE; // Set state as subclassed
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}//End of the hook procedure
//----------------------------------------------------------------------------------------------------
//The MouseProc hook Proc(Computer Based Training Hook)
LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if(wParam == WM_MOUSEMOVE ){
POINT pt;
GetCursorPos(&pt);
ScreenToClient(g_Data->hTarget,&pt);
pt.x = pt.x - 12;
pt.y = pt.y - 56;
if(pt.x < 0 || pt.y < 0 ){
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int col = pt.x/16;
int row = pt.y/16;
static int oldrow = -1;
static int oldcol = -1;
if((oldrow == row) && (oldcol == col) ){
return CallNextHookEx(NULL, nCode, wParam, lParam);
}else{
delete ht;
ht = NULL;
}
oldrow = row;
oldcol = col;
unsigned long nSize=1;
unsigned long lpNumberOfByteRead;
PBYTE lpBuffer = StrAlloc(nSize);
ZeroMemory(lpBuffer,nSize);
unsigned long MineID;
GetWindowThreadProcessId(g_Data->hTarget,&MineID);
HANDLE Mine = OpenProcess(PROCESS_VM_READ,true,MineID);
int mWidth,mHeight;
if(ReadProcessMemory(Mine,(LPCVOID)MineWidth,(LPVOID)lpBuffer,nSize,&lpNumberOfByteRead))
{
mWidth=*(unsigned long *)lpBuffer;
}
if(ReadProcessMemory(Mine,(LPCVOID)MineHeight,(LPVOID)lpBuffer,nSize,&lpNumberOfByteRead))
{
mHeight=*(unsigned long *)lpBuffer;
}
if(row <= mHeight && col<=mWidth && ReadProcessMemory(Mine,(LPCVOID)(MineStartAddress+row*32+col),(LPVOID)lpBuffer,nSize,&lpNumberOfByteRead)){
ht = new THintWindow(g_Data->hTarget);
pt.x = pt.x + 15;
pt.y = pt.y + 48;
ClientToScreen(g_Data->hTarget , &pt);
if(*(unsigned long *)lpBuffer != 0x8F)
{
TRect rect = Rect(pt.x, pt.y , pt.x + ht->Canvas->TextWidth("Not Lei")+ 5 , pt.y + ht->Canvas->TextHeight("Not Lei")+ 2);
ht->ActivateHint(rect, "Not Lei");
}else{
TRect rect = Rect(pt.x, pt.y , pt.x + ht->Canvas->TextWidth("Lei")+ 5 , pt.y + ht->Canvas->TextHeight("Lei")+ 2);
ht->ActivateHint(rect, "Lei");
}
}
CloseHandle(g_Data->hTarget);
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}//End of the hook procedure
//----------------------------------------------------------------------------------------------------
HANDLE MapGlobalData(const AnsiString MapName, int Size, LPVOID &P)
{
HANDLE ret = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, Size, MapName.c_str());
if(ret == 0){
if(GetLastError() == ERROR_ALREADY_EXISTS) {
ret = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, MapName.c_str());
if(ret == 0) return ret;
}else{
return ret;
}
}
P = (LPVOID)MapViewOfFile(ret, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (P == NULL) {
CloseHandle(ret);
ret = 0;
}
return ret;
}
//----------------------------------------------------------------------------------------------------
void ReleaseGlobalData(HANDLE handle, void* &Ptr)
{
if(Ptr){
UnmapViewOfFile(Ptr);
Ptr = NULL;
}
if(handle != 0){
CloseHandle(handle);
handle = 0;
}
}
//----------------------------------------------------------------------------------------------------