给初学者:用VB写外挂 ———— 如何给外挂定义一组热键:红色警戒五项属性修改器VB版

原文地址为: 给初学者:用VB写外挂 ———— 如何给外挂定义一组热键:红色警戒五项属性修改器VB版

 

上次说要给大家讲讲怎么定义热键,不过翻看了一下,网上的文件很多了,而且刚写完这个代码看时间已经快上班了,今天就贴个刚完成的代码大家学习吧!继续我们的红色警戒修改器,继续修改上篇的代码就可以了。本代码介绍的内容:

1、给程序定义多个全局热键,其中组合键没有体现,网上是有这个代码的,不过还是贴在下面,我是根据这个代码修改的

2、外挂基本知识

以下是定义全局热键(组合键)代码:(在VB编程资源大全代码光盘上复制的,作者未知;按ALT+SHIFT+G测试)

'以下在.Bas
Option Explicit

Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long) As Long

Public Const WM_HOTKEY = &H312
Public Const MOD_ALT = &H1
Public Const MOD_CONTROL = &H2
Public Const MOD_SHIFT = &H4
Public Const GWL_WNDPROC = (-4)

Public preWinProc As Long
Public Modifiers As Long, uVirtKey As Long, idHotKey As Long

Private Type taLong
ll As Long
End Type

Private Type t2Int
lWord As Integer
hword As Integer
End Type

Public Function wndproc(ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_HOTKEY Then
If wParam = idHotKey Then
Dim lp As taLong, i2 As t2Int
lp.ll = lParam
LSet i2 = lp
If (i2.lWord = Modifiers) And i2.hword = uVirtKey Then
Debug.Print "HotKey Shift-Alt-G Pressed "
Shell "notepad", vbNormalFocus
End If
End If
End If
'将之送往原来的Window Procedure
wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
End Function

'以下在 Form
Sub Form_Load()
Dim ret As Long
preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf wndproc)
idHotKey = 1 'in the range &h0000 through &hBFFF
Modifiers = MOD_ALT + MOD_SHIFT
uVirtKey = vbKeyG
ret = RegisterHotKey(Me.hwnd, idHotKey, Modifiers, uVirtKey)
End Sub

Private Sub Form_Unload(Cancel As Integer)
Dim ret As Long
'取消Message的截取,而使之又只送往原来的Window Procedure
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc)
Call UnregisterHotKey(Me.hwnd, uVirtKey)
End Sub

以上代码就可以定义一个组合键为全局热键,说明已经很清楚了,代码也比较好看,大家自己看吧。

以下是我写的红色警戒5项修改器代码,虽然叫了5项,其实F8的功能没实现,太麻烦了,几千个内存地址需要读写。所以,只实现了4项:加钱,和大家熟悉的那个是一样的钱数,POWER加满(建筑越多,电就越多,呵呵),快速建筑,立即胜利。不罗嗦了,代码在XP(不知道SP几,没关心过这个),VB6+SP6下测试通过。

以下在模块(和上一个的差不多,只是把读内存的改回去了,又加了全局热键需要的API)

Option Explicit

'查找窗体写内存等
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const SYNCHRONIZE = &H100000
Private Const SPECIFIC_RIGHTS_ALL = &HFFFF
Private Const STANDARD_RIGHTS_ALL = &H1F0000
Private Const PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
Private Const PROCESS_VM_OPERATION = &H8&
Private Const PROCESS_VM_READ = &H10&
Private Const PROCESS_VM_WRITE = &H20&

'权限提升
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long

Private Const TOKEN_ASSIGN_PRIMARY = &H1
Private Const TOKEN_DUPLICATE = (&H2)
Private Const TOKEN_IMPERSONATE = (&H4)
Private Const TOKEN_QUERY = (&H8)
Private Const TOKEN_QUERY_SOURCE = (&H10)
Private Const TOKEN_ADJUST_PRIVILEGES = (&H20)
Private Const TOKEN_ADJUST_GROUPS = (&H40)
Private Const TOKEN_ADJUST_DEFAULT = (&H80)
Private Const TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or TOKEN_ASSIGN_PRIMARY Or _
TOKEN_DUPLICATE Or TOKEN_IMPERSONATE Or TOKEN_QUERY Or TOKEN_QUERY_SOURCE Or _
TOKEN_ADJUST_PRIVILEGES Or TOKEN_ADJUST_GROUPS Or TOKEN_ADJUST_DEFAULT)
Private Const SE_PRIVILEGE_ENABLED = &H2
Private Const ANYSIZE_ARRAY = 1

Private Type LUID
    lowpart As Long
    highpart As Long
End Type

Private Type LUID_AND_ATTRIBUTES
    pLuid As LUID
    Attributes As Long
End Type

Private Type TOKEN_PRIVILEGES
    PrivilegeCount As Long
    Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
End Type

'热键
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Public Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long) As Long

Public Const WM_HOTKEY = &H312
Public Const GWL_WNDPROC = (-4)

Public preWinProc As Long

Public uVirtKeyF5 As Long
Public uVirtKeyF6 As Long
Public uVirtKeyF7 As Long
Public uVirtKeyF8 As Long
Public uVirtKeyF9 As Long

Public idHotKey As Long

' 储存进程标识符( Process Id )

Private GamePid As Long

'提升权限为高
Public Function ToKen() As Boolean
Dim hdlProcessHandle As Long
Dim hdlTokenHandle As Long
Dim tmpLuid As LUID
Dim tkp As TOKEN_PRIVILEGES
Dim tkpNewButIgnored As TOKEN_PRIVILEGES
Dim lBufferNeeded As Long
Dim lp As Long
hdlProcessHandle = GetCurrentProcess()
lp = OpenProcessToken(hdlProcessHandle, TOKEN_ALL_ACCESS, hdlTokenHandle)
lp = LookupPrivilegeValue("", "SeDebugPrivilege", tmpLuid)
tkp.PrivilegeCount = 1
tkp.Privileges(0).pLuid = tmpLuid
tkp.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
lp = AdjustTokenPrivileges(hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded)
ToKen = lp
End Function

'获取内存内容
Public Function GetData(ByVal lppid As Long, ByVal lpADDress As Long, Optional ByVal dtLen As Long = 4) As Long
Dim pHandle As Long ' 储存进程句柄
' 使用进程标识符取得进程句柄
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, lppid)
' 在内存地址中读取数据
ReadProcessMemory pHandle, ByVal lpADDress, ByVal VarPtr(GetData), dtLen, 0&
' 关闭进程句柄
CloseHandle pHandle
End Function

'将修改内存
Public Function SetData(ByVal lppid As Long, ByVal lpDestAddr As Long, lpSrcAddr() As Byte, Optional ByVal dtLen As Long = 4) As Boolean
On Error GoTo mErr
Dim lBytesReadWrite As Long
Dim pHandle As Long ' 储存进程句柄
' 使用进程标识符取得进程句柄
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, lppid)
WriteProcessMemory pHandle, ByVal lpDestAddr, ByVal VarPtr(lpSrcAddr(0)), dtLen, 0&
' 关闭进程句柄
CloseHandle pHandle
SetData = True
mErr:
End Function

Public Function GetPid(lpClassName As String, lpWindowName As String) As Long
' 取得进程标识符
GetWindowThreadProcessId FindWindow(lpClassName, lpWindowName), GetPid
End Function


Public Sub Xiugai(ByVal Fx As String)

Dim addrEAX As Long
Dim mBuff() As Byte
On Error GoTo m_Err

GamePid = GetPid("Red Alert 2", "Red Alert 2")

If GamePid = 0 Then
    Form1!Label4.Caption = "请先启动游戏!"
    Exit Sub
End If


'获取版本标志
If GetData(GamePid, &H77E41A90, 1) <> 85 Then
    Form1!Label4.Caption = "版本不符!"
    Exit Sub
End If

Select Case Fx
'*******************************************************
'F5:修改金钱
'*******************************************************
Case "F5"
'获取寄存器地址addrEAX + &H24C
addrEAX = GetData(GamePid, &HA35DB4, 4)
Debug.Print Hex(addrEAX + &H24C)

'写入金钱
ReDim mBuff(3) As Byte  '要写入的金钱
mBuff(0) = &HFF
mBuff(1) = &HFF
mBuff(2) = &H1
mBuff(3) = &H0
SetData GamePid, addrEAX + &H24C, mBuff()
'*******************************************************
'F6电力全满
'*******************************************************
Case "F6"
'清除电力测试代码
ReDim mBuff(5) As Byte  '要写入的NOP
mBuff(0) = &H90
mBuff(1) = &H90
mBuff(2) = &H90
mBuff(3) = &H90
mBuff(4) = &H90
mBuff(5) = &H90
SetData GamePid, &H4F2D88, mBuff(), 6
SetData GamePid, &H4F2D0F, mBuff(), 6
'读取电力数据指针
addrEAX = GetData(GamePid, &HA35DB4, 4)
Debug.Print Hex(addrEAX + &H52D0)
'写入电力数据数值,最大65535
mBuff(0) = &HFF
mBuff(1) = &HFF
SetData GamePid, addrEAX + &H52D0, mBuff(), 2
'*******************************************************
'F7快速建造
'*******************************************************
Case "F7"
ReDim mBuff(7) As Byte  '要写入的NOP
mBuff(0) = &HC0
mBuff(1) = &H36
mBuff(2) = &H0
mBuff(3) = &H0
mBuff(4) = &H0
mBuff(5) = &H90
mBuff(6) = &H90
mBuff(7) = &H90
SetData GamePid, &H4B93DA, mBuff(), 1
mBuff(0) = &HBA
SetData GamePid, &H4B935F, mBuff(), 8
'*******************************************************
'F8显示地图
'*******************************************************
Case "F8"
GoTo m_Err
ReDim mBuff(0) As Byte  '要写入的NOP
mBuff(0) = &H8
'简直麻烦透了啊...光写就1000多次.写的都是这个值
'*******************************************************
'F9立即胜利
'*******************************************************
Case "F9"
ReDim mBuff(0) As Byte
mBuff(0) = &H8
SetData GamePid, &HA35DB1, mBuff(), 1
End Select

Form1!Label4.Caption = Fx & "修改成功!"

Exit Sub
m_Err:
Form1!Label4.Caption = "修改失败啦!"

End Sub

'热键

Public Function wndproc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_HOTKEY Then
    If wParam <= idHotKey Then
        Select Case lParam
            Case 7602176
                Xiugai "F5"
            Case 7667712
                Xiugai "F6"
            Case 7733248
                Xiugai "F7"
            Case 7798784
                Xiugai "F8"
            Case 7864320
                Xiugai "F9"
        End Select
       
    End If
End If
'将之送往原来的Window Procedure
wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
End Function

按惯例以下另存为*.FRM文件,这次由于在模块里操作了窗体中的控件,请保存以下内容为FORM1.FRM

VERSION 5.00
Begin VB.Form Form1
   AutoRedraw      =   -1  'True
   BorderStyle     =   3  'Fixed Dialog
   Caption         =   "RA2修改器VB版"
   ClientHeight    =   1455
   ClientLeft      =   45
   ClientTop       =   330
   ClientWidth     =   1815
   LinkTopic       =   "RA2修改器VB版"
   MaxButton       =   0   'False
   MinButton       =   0   'False
   ScaleHeight     =   1455
   ScaleWidth      =   1815
   ShowInTaskbar   =   0   'False
   StartUpPosition =   3  '窗口缺省
   Begin VB.Frame Frame1
      Height          =   375
      Left            =   0
      TabIndex        =   1
      Top             =   1080
      Width           =   1815
      Begin VB.Label Label4
         Caption         =   "启动成功"
         Height          =   195
         Left            =   105
         TabIndex        =   2
         Top             =   135
         Width           =   1575
      End
   End
   Begin VB.Label LabMSG
      Height          =   1215
      Left            =   0
      TabIndex        =   0
      Top             =   0
      Width           =   1815
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'请保留作者信息:
'ZCSOR于06-8-30开发
'E-MAIL:[email protected]

Option Explicit


Private Sub Form_Load()
ToKen
'定义热键
Dim ret As Long

preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf wndproc)

    uVirtKeyF5 = vbKeyF5   'F5
    uVirtKeyF6 = vbKeyF6   'F6
    uVirtKeyF7 = vbKeyF7   'F7
    uVirtKeyF8 = vbKeyF8   'F8
    uVirtKeyF9 = vbKeyF9   'F9
   
    idHotKey = idHotKey + 1: ret = RegisterHotKey(Me.hwnd, idHotKey, 0, uVirtKeyF5)
    idHotKey = idHotKey + 1: ret = RegisterHotKey(Me.hwnd, idHotKey, 0, uVirtKeyF6)
    idHotKey = idHotKey + 1: ret = RegisterHotKey(Me.hwnd, idHotKey, 0, uVirtKeyF7)
    idHotKey = idHotKey + 1: ret = RegisterHotKey(Me.hwnd, idHotKey, 0, uVirtKeyF8)
    idHotKey = idHotKey + 1: ret = RegisterHotKey(Me.hwnd, idHotKey, 0, uVirtKeyF9)

LabMSG.Caption = "红色警戒V1.06修改器" & vbCrLf & _
                "F5:获取金钱" & vbCrLf & _
                "F6:电力全满" & vbCrLf & _
                "F7:快速建造" & vbCrLf & _
                "F8:无功能:(" & vbCrLf & _
                "F9:立即胜利"

End Sub


Private Sub Form_Unload(Cancel As Integer)
Dim ret As Long
'取消Message的截取,而使之又只送往原来的Window Procedure
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc)
Call UnregisterHotKey(Me.hwnd, uVirtKeyF5)
Call UnregisterHotKey(Me.hwnd, uVirtKeyF6)
Call UnregisterHotKey(Me.hwnd, uVirtKeyF7)
Call UnregisterHotKey(Me.hwnd, uVirtKeyF8)
Call UnregisterHotKey(Me.hwnd, uVirtKeyF9)
End Sub

好了,现在可以运行你的游戏RA2游戏了,1.06版哦~呵呵,我只安了1.06,如果有时间会把地图全开写出来的,而且会整和几个版本的修改器到一起,这样才实用麻!不过可能要等一段时间了,最近还是比较忙~~~

代码下载地址:http://down.csdn.net/html/2006-08/31/158795.html (现在可以下了,前几天可能是还没通过审核)

有朋友发MAIL给我说总提示版本不对,虽然我测试没发现类似问题,呵呵,把

'获取版本标志
If GetData(GamePid, &H77E41A90, 1) <> 85 Then
    Form1!Label4.Caption = "版本不符!"
    Exit Sub
End If

去掉重新编译即可。

这里最后提示一个技巧,可能有些同志不明白我是怎么得到寄存器地址的,例如addrEAX = GetData(GamePid, &HA35DB4, 4)其实很简单,你可以去跟踪那个现成的修改器,或者继续看:

当用CE确定了金钱地址以后,发现语句为EAX+24C,而当前金钱的地址-24C就是指针指向地址了,你可以用CE的指针跟踪(非常慢),我是这样做的:将当前金钱地址-24C,然后用CE搜索这个16进制值,得到一些地址,重新运行游戏,重复过程,得到另一个地址列表,再重复,直到你找到那个不变的,呵呵,其实,在公共变量区内的那些基本是不变的,我直接取了绿色标志的那行,就是&HA35DB4!

好了,至此大家所有的疑惑应该已经都解决了,最后说明一下,我跟踪了一下那个英文版的修改器,他读指针时确实也读了&HA35DB4这个位置,但是为了避免嫌疑还是把我得到的方法告诉大家,后面的地址也如此即可得到!


转载请注明本文地址: 给初学者:用VB写外挂 ———— 如何给外挂定义一组热键:红色警戒五项属性修改器VB版

猜你喜欢

转载自blog.csdn.net/wcqlwyt/article/details/80649620
今日推荐