zoukankan      html  css  js  c++  java
  • 菜鸟写游戏外挂

    偶与同学玩游戏时,不仅想起作弊,是可以让我所做的操作更少呢?或者改掉程序里的数据呢?就这样我开始写这个的一个程序。向程序发消息,从程序得到消息,然后在程序内存空间找我要的数据,然后再更改。在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 LongAs 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 3As Byte
        
    Dim dst(0 To 3As 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, 4Then
                                
    '已找到需要的数据
                                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 LongAs Long
            
        
    Dim r As Long, lenmbi As Long
        
    Dim mbi As MEMORY_BASIC_INFORMATION
        
    Dim src(0 To 3As 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 LongAs 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 LongAs Long
    以上就是我这次做完这个东东后写的,如果有错误,请与我联系EMAIL:yhb_yinhaibo@163.com

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

  • 相关阅读:
    typescript 深层次对象内层(N)转外层(N),支持多层级递归转换,多应用于多语言数据结构转换
    js 柯里化、深拷贝、浅拷贝
    js IntersectionObserver api
    javascript-state-machine
    NodeJs的CommonJS模块规范
    js 动画
    【THUPC 2018】赛艇
    【CF528D】Fuzzy Search
    【UR #6】懒癌
    【HNOI 2019】JOJO
  • 原文地址:https://www.cnblogs.com/yin138/p/4902279.html
Copyright © 2011-2022 走看看