菜鸟写游戏外挂

偶与同学玩游戏时,不仅想起作弊,是可以让我所做的操作更少呢?或者改掉程序里的数据呢?就这样我开始写这个的一个程序。向程序发消息,从程序得到消息,然后在程序内存空间找我要的数据,然后再更改。在Windows下做这些事情好像不是很难,但我遇到的问题可以说是一个API就是一个问题,当然最后还是写了一个小模型。现将经验写于此记之,给遇上同样问题的同行以帮助, 并盼望更多的高手以指教。(开发平台:WinXP,VB6,VC6)

>>使用Hook(钩子)去拦截游戏进程中的键盘消息

在这个过程中,我为了写一个全局的钩子,所以我得写一个DLL,而这个DLL一定要有一个共享节,不然就不能得到所有GUI进程的键盘消息。在这里我写了好长的时间,我的那个DLL就是不行。后来我找到《Visual Basic Win32 API》上面的源代码,才得以解决。

//  Set up shared data section in DLL
#pragma  data_seg("Shared")
HHOOK ghHook 
=  NULL;
HHOOK ghKBHook 
=  NULL;
HANDLE ghSubclassedForm 
=  NULL;
int  lMsgID;
#pragma  data_seg()

//  Tell linker to make this section shared and read-write
#pragma  comment(linker, "/section:Shared,rws")

以上就是我写DLL时的共享节,当时我看到书上说可以在编译器上设置/section:Shared,rws参数,但是编译器总是提示EXP中找不到该节,而生成的DLL文件就只能在本进程注入(SetWindowsHookEx)。我百思不得其解,后来都怀疑是不是机器有问题呢?最终,我还是以别人写的源代码改写的,才没有问题,我想应该是我编译设置有问题,但是现在我还没有找到,幸好问题得到了解决,我的DLL可以注入到我想注入的GUI进程。

>>在VB中写API的一些感悟

在VB下开发已经很长时间了,VB本身的问题还是不成问题了,但是一但要用到API,问题就多了。以下就我个人在用VB时,出错较多的几点说一下。

1、不要太想信API函数声明软件,因为有很多问题就是它引起的,比如在传参数上面,如果出现保护异常,那大部分是因为参数声明有误,比如需要地址的时候,就不能使用传引用,或者直接传变量地址过去,比如ReadProcessMemory函数第二个参数不能传地址,因为他代表的就是一个值而已,而API声明软件就认为其是一个地址,将参数声明引用,这样的话,是很容易出问题的。

2、在不太明白参数声明的时候,调用函数的时候一定要带byval调用,像用VarPtr函数得到地址后,就一个要传值,不然程序就得不到正确的结果。

3、在不是很明白VB中的String时,与API交互的时候就不要用。这也是所谓的BSTR,COM中用的,我现在也不太懂。如果需要用字符串的时候,就使用BYTE类型,得到结果后使用StrConv将其转换过来就可以了。《Visual Basic Win32 API》这本书上讲得很清楚,很经典的。当然《Advanced VB》那本书就是很牛的了。

>>在读写其它进程空间数据时的问题

如果对Windows进程与内存管理不是很熟悉的时候写这样的程序,真是问题很多啊,而且是在VB这样的环境下面,更是问题多多,几乎是每一个API函数就是一个问题。笔者就是这样子将一个程序写完的,其中的艰辛不言而喻啦。在读内存的时候主要问题就是权限与指针问题,你不要想从WINDOWS那里得到一些错误帮助信息,因为错误之后得到的结果就是“操作成功完成。”,所以一旦出现问题,就不知错在那里。比如在使用ReadProcessMemory函数的时候,如果具有PROCESS_VM_READ面不拥用PROCESS_VM_OPERATION打开进程(OpenProcess)时,你就甭想得到数据。很多时间你拥有PROCESS_VM_WRITE的时候,还是不能得到写进程地址空间的权限,最好就是PROCESS_ALL_ACCESS这样的标志打开的进程就比较爽了。但有的还是不能写,而得到该区域的权限与状态(VirtualQueryEx)都提示可写,可就是写不了,我也不知道是什么原因。

 

Public   Function  VirtualQueryValue( _
        ByVal hProcess 
As   Long , _
        ByVal lpBaseAddr 
As   Long , _
        ByVal idxFind 
As   Long , _
        ByVal x 
As   Long As   Long
        
    
Dim  mPageSize  As   Long         ' 系统最小页尺寸
     Dim  mMinAppAddr  As   Long
    
Dim  mMaxAppAddr  As   Long

    
Dim  mbi  As  MEMORY_BASIC_INFORMATION  ' 内存基本信息
     Dim  sysInfo  As  SYSTEM_INFO_ART
    
Dim  mBaseAddr  As   Long
    
Dim  mBuffer()  As   Byte

    
Dim  midxFind  As   Long   ' 找到计数
    midxFind  =   0
    
    
' 获得系统信息
     Dim  r  As   Long
    
Call  GetSystemInfo_ATR(sysInfo)
    mPageSize 
=  sysInfo.dwPageSize
    mMinAppAddr 
=  sysInfo.lpMinimumApplicationAddress
    mMaxAppAddr 
=  sysInfo.lpMaximumApplicationAddress

    
Dim  lenmbi  As   Long
    
Dim  i  As   Long
    
Dim  mNumberOfBytesRead   As   Long
    
Dim  temp  As   Long   ' 用于从4个BYTE中得到一个LONG数据
    
    
' 用于将内存存储模式转换为实际可读模式
     Dim  src( 0   To   3 As   Byte
    
Dim  dst( 0   To   3 As   Byte
    
    
' 确定地址范围
    lenmbi  =  LenB(mbi)
    
If  lpBaseAddr  <  mMinAppAddr  Then
        mBaseAddr 
=  mMinAppAddr
    
Else
        mBaseAddr 
=  lpBaseAddr
    
End   If
    r 
=  VirtualQueryEx(hProcess, mBaseAddr, mbi, lenmbi)

    
' 枚举所有进程地址空间
     Do   While  (r)
        
' 处理内存信息
         If  r  <>  lenmbi  Then   Exit   Do   ' 返回值不正常则终止
         If  mbi.dwState  And  MEM_COMMIT  Then
            
' 如果该区域是可读就试着读它
             If   0   =  (mbi.dwProtect  And  (PAGE_EXECUTE  Or  PAGE_NOACCESS))  Then
            
                
' 重新定义缓冲区大小
                 ReDim  mBuffer( 0   To  mbi.dwRegionSize)
                
' 读内存
                r  =  ReadProcessMemory(hProcess, mBaseAddr, _
                        ByVal VarPtr(mBuffer(
0 )), mPageSize, mNumberOfBytesRead)
                
If  mNumberOfBytesRead  <>  mPageSize  Then
                    Debug.Print 
" Err--ReadProcessMemory: "   &  GetLastErrMsg
                
Else
                    
For  i  =   LBound (mBuffer)  To   UBound (mBuffer)  -   1  Step  4
                        
' 得到源与目标的内存模式拷贝
                        CopyMemory src( 0 ), mBuffer(i),  4
                        CopyMemory dst(
0 ), x,  4
                        
                        
If  ComareByteArr(src, dst,  4 Then
                            
' 已找到需要的数据
                            midxFind  =  midxFind  +   1
                            
' 如果找到了指定索引的数据,则返回
                             If  idxFind  =  midxFind  Then
                                VirtualQueryValue 
=  mBaseAddr  +  i
                                
Exit   Function
                            
End   If
                            
' 如果不是指定索引,则继续
                         End   If
                    
Next  i
                
End   If
            
End   If    ' PAGE_READWRITE
         End   If
        
' 向下搜索
         On   Error   Resume   Next
        
If  mBaseAddr  <   0   Then   Exit   Do   ' 超过VB表示范围
        mBaseAddr  =  mBaseAddr  +  mbi.dwRegionSize
        
' 如果完成所有地址搜索,则退出
         If  mBaseAddr  >  mMaxAppAddr  Then   Exit   Do
        
On   Error   GoTo   0
        DoEvents

        r 
=  VirtualQueryEx(hProcess, mBaseAddr, mbi, lenmbi)
    
Loop
End Function

' 修改指定内存值
Function  VirtualModifyValue(ByVal hProcess  As   Long , _
        ByVal lpAddress 
As   Long , ByVal x  As   Long As   Long
        
    
Dim  r  As   Long , lenmbi  As   Long
    
Dim  mbi  As  MEMORY_BASIC_INFORMATION
    
Dim  src( 0   To   3 As   Byte
    
Dim  s  As   String
    lenmbi 
=  LenB(mbi)
    
    
' 查看该区域是否可写
    r  =  VirtualQueryEx(hProcess, lpAddress, mbi, lenmbi)
    
' 不可写则退出
     If   0   <>  (mbi.dwProtect  And  PAGE_NOACCESS)  Then   Exit   Function
    
If  mbi.dwState  <>  MEM_COMMIT  Then   Exit   Function
    
' 试图改写内存
    CopyMemory src( 0 ), x,  4
    VirtualModifyValue 
=  WriteProcessMemory(hProcess, ByVal lpAddress, ByVal VarPtr(src( 0 )),  4 , ByVal  0 & )
End Function

以上是用VB写的读写内存地址空间的一段代码,我写了好久好久,遇到了好多好多问题最终,因为游戏数据在空间中找不到(也许是加密了吧),而告终,但我还是知道如何修改我自己写的俄罗斯方块的分数了。以下就重要函数的声明:

Declare  Function  VirtualQueryEx Lib  " kernel32 "  ( _
   ByVal hProcess 
As   Long , _
   ByVal lpAddress 
As   Long , _
   ByRef lpBuffer 
As  MEMORY_BASIC_INFORMATION, _
   ByVal dwLength 
As   Long  _
As   Long

Public  Declare  Function  WriteProcessMemory Lib  " kernel32.dll "  ( _
            ByVal hProcess 
As   Long , _
            ByVal lpBaseAddress 
As   Long , _
            ByRef lpBuffer 
As   Long , _
            ByVal nSize 
As   Long , _
            ByRef lpNumberOfBytesWritten 
As   Long As   Long
            
Public  Declare  Function  ReadProcessMemory Lib  " kernel32.dll "  ( _
            ByVal hProcess 
As   Long , _
            ByVal lpBaseAddress 
As   Long , _
            ByRef lpBuffer 
As   Long , _
            ByVal nSize 
As   Long , _
            ByRef lpNumberOfBytesWritten 
As   Long As   Long
以上就是我这次做完这个东东后写的,如果有错误,请与我联系EMAIL: yhb_yinhaibo@163.com

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/yin138/archive/2006/10/12/4902279.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值