扫雷游戏外挂实例。
实现功能:
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
;
}
}
//
----------------------------------------------------------------------------------------------------