VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
查看: 4427|回复: 2

[转帖] 如何扫描/读写外部程序的内存|如何对应某程序内存使用状态

[复制链接]
 楼主| 发表于 2009-8-7 07:34:38 | 显示全部楼层 |阅读模式
如何扫描/读写外部程序的内存|如何对应某程序内存使用状态


如何扫描外部程序的内存

原文地址:http://sunh.hosp.ncku.edu.tw/~cww/html/q00534.html

说明


这是市面上游戏修改器常见的功能 实际上难度并不高 只要统合如何读写外部程序内存以及如何对应外部程序内存使用状态 然后就可以轻松写出来了 主要步骤如下


定出内存区段


因为要搜寻的是变量,内存属性必须是可擦写的,所以一般而言只要定出可擦写的区段即可就是属性为ERW(可执行,可读,可写),RW(可读,可写)的内存区段


另外 关于程序寻址的范围

      • Dos底下是4K到4MB的范围
      • Win32底下应用程序是从&H400000到&H7FFFFFFF(2GB的范围)
               这个值可以从GetSystemInfo中取得       NT会有点不同 不过为了兼容一般应用程序还是会订在&H400000以后

GetSystemInfo hSysInfo
基底寻址=hSysInfo.lpMinimumApplicationAddress
最高寻址=hSysInfo.lpMinimumApplicationAddress


除非是用在Driver或是共享内存方面才有可能用到3GB以上的范围一般而言 只要寻址2GB的应用程序地址即可


搜寻


其实这就是在一个数组中找出某个值 这是在简单不过了 只要这样


For i = 1 to N
   If b(i) = H Then
      '
纪录地址
   End If
Next


以下程序是示范搜寻Byte型态的变量 如果要搜寻Integer或是Long型态的变量就交给网友自行撰写了 方法都一样 只是byte只要比对一个Byte,Integer和Long分别要比对2和4个Byte..


程序


'这个程序需要一个Command,两个Text,一个ListBox
Private Sub Command1_Click()
Dim mbi As MEMORY_BASIC_INFORMATION
Dim hwnd As Long, hProcessID As Long, hProcess As Long
Dim tmpBassAddr As Double, lBassAddr As Long
Dim BassAddr() As Long, PageSize() As Long, PageNum As Long

List1.Clear

'Text1
输入要搜寻窗口的标题
hWnd = FindWindow(vbNullString,Text1.Text)
If hWnd = 0 Then
    MsgBox "
无法找到该窗口"
    Exit Sub
End If

'由窗口的Handle取得Process ID
Call GetWindowThreadProcessId(hWnd, hProcessID)
If hProcessID = 0 Then
    MsgBox "无法取得ProcessID"
    Exit Sub
End If
   
'开启该Process
hProcess = OpenProcess(PROCESS_ALL_ACCESS _
, 0, hProcessID)
If hProcess = 0 Then
    MsgBox "无法开启该Process"
    Exit Sub
End If

'------------------以下是对应区块的程序----------------------------
'为了谨慎起见 寻址由0开始 一直到&H7FFFFFFF
Do While VirtualQueryEx(hProcess, ByVallBassAddr, mbi, Len(mbi)) '若执行成功
   
    '预防溢位 由于Long型态最大值是&H7FFFFFFF
    '如果寻址超出这个范围就离开
    tmpBassAddr = mbi.BaseAddress
    tmpBassAddr = tmpBassAddr + mbi.RegionSize
    If tmpBassAddr > &H7FFFFFFF Then
        Exit Do
    End If
   
    '定出已配置解渴读写的区块
    If mbi.State = MEM_COMMITThen '已配置
        Ifmbi.Protect And (PAGE_READWRITE Or PAGE_EXECUTE_READWRITE OrPAGE_EXECUTE_WRITECOPY) Then
            '符合 纪录基地址以及区块大小
ReDim Preserve BassAddr(PageNum)
            ReDimPreserve PageSize(PageNum)
           BassAddr(PageNum) = mbi.BaseAddress '基地址
           PageSize(PageNum) = mbi.RegionSize '区块大小
           PageNum = PageNum + 1 '纪录总区块数
        EndIf
    End If
   
    lBassAddr = tmpBassAddr '对应下一笔
Loop
'-----------------------结束对应区块-----------------------

'-----------------------以下是搜寻的部分-----------------
Dim data() As Byte, i As Long, j As Long, k AsLong
Dim finded As Long, fio As Byte
fio = CByte(Text2.Text) '要搜寻的数值
For i = 0 To PageNum - 1
    ReDim data(1 To PageSize(i)) '根据区块大小配置内存
    '读取内存
    ReadProcessMemory hProcess,ByVal BassAddr(i), data(1), PageSize(i), ByVal 0&

    '比对
    For j = 1 To PageSize(i)
        If data(j) = fio Then
           List1.AddItem BassAddr(i) + j - 1
            DoEvents
            finded =finded + 1
        End If
    Next
Next
'-----------------------结束搜寻的部分-----------------

MsgBox "执行完毕 一共找到" & finded & "笔数据"

'关闭该Process
CloseHandle hProcess

'释放数组配置的内存
Erase BassAddr
Erase PageSize
Erase data
End Sub


范例程序下载




文件出处


Honey


整理时间

2002'3,30.



如何读写外部程序的内存








说明


这是我在留言版上看到的问题,其实就是要做一个简单的内存修改器,我所公开的这个程序许多部分我已经把他简化了,一方面关于内存有许许多多东西必须要先知道的,这要说明可是要用上许多篇幅,所以我只针对读取及写入的核心Read/WriteProcessMemory下手


Read/WriteProcessMemory(ByVal hProcess As Long,lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long,lpNumberOfBytesWritten As Long) As Long

  hProcess:
        
这是要读取写入的Process的Handle
  lpBaseAddress:
      
这是要读取或是写入的基地址
  lpBuffer:
       这是用来存取要读取或写入的数据
  nSize:
  
     这是lpBuffer的大小
  lpNumberOfBytesWritten:
  
     这是该程序执行后实际读取的数据大小


比较大的问题是如何取得Process的Handle,一般是从FindWindow开始取得该窗口的handle,如果要取得标题是"记事本"窗口的Handle只要这样
     Dim hWnd As Long '窗口的Handle
     hWnd =FindWindow(vbNullString, "记事本")

取得窗口的Handle后就可以用GetWindowThreadProcessId取得该Process的ID
     Dim ProcessID As Long
     GetWindowThreadProcessId hWnd, ProcessID

之后只要用OpenProcess开启该ProcessID即可取得Process的Handle
     Dim hProcess As Long
     hProcess = OpenProcess(PROCESS_ALL_ACCESS _
                      , 0, hProcessID)
' 由于要读写该Process所以必须加上PROCESS_VM_READ
' 和PROCESS_VM_WRITE 也可以直接以PROCESS_ALL_ACCESS取代全部




有兴趣的读者可以下载此范例程序AccessProcessMemory.Imp
这个范例中有个执行文件test.exe可以作为做读写的目标
执行文件的按钮上方文字显示该变量的地址 只要在程序的Text2或Text4填入该地址即可对该变量做读写的动作 之后你可以按下test.exe的按键实际确认变量的值 是否已被修改


程序


'-----------------------------------------------------------------------------------------------
'
以下程序在模块
Option Explicit
Public Type SYSTEM_INFO
        dwOemID As Long
        dwPageSize As Long
        lpMinimumApplicationAddress As Long
        lpMaximumApplicationAddress As Long
        dwActiveProcessorMask As Long
        dwNumberOrfProcessors As Long
        dwProcessorType As Long
        dwAllocationGranularity As Long
        dwReserved As Long
End Type
Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
Public Const SYNCHRONIZE = &H100000
Public Const SPECIFIC_RIGHTS_ALL = &HFFFF
Public Const STANDARD_RIGHTS_ALL = &H1F0000
Public Const PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or&HFFF
Public Const PROCESS_VM_OPERATION = &H8&
Public Const PROCESS_VM_READ = &H10&
Public Const PROCESS_VM_WRITE = &H20&
Public Declare Sub CopyMemory Lib "kernel32" Alias"RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length AsLong)
Public Declare Function ReadProcessMemory Lib "kernel32" (ByValhProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long,lpNumberOfBytesWritten As Long) As Long
Public Declare Function WriteProcessMemory Lib "kernel32" (ByValhProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long,lpNumberOfBytesWritten As Long) As Long
Public Declare Function OpenProcess Lib "kernel32" (ByValdwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId AsLong) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject AsLong) As Long
Public Declare Sub GetSystemInfo Lib "kernel32" (lpSystemInfo AsSYSTEM_INFO)
Public Declare Function GetWindowThreadProcessId Lib "user32" _
(ByVal hWnd As Long, lpdwProcessId As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias"FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName AsString) As Long
'----------------------------------------------------------------------------------------------
'
以下程序在Form中
Option Explicit
Dim hProcess As Long
Dim hProcessID As Long
Dim hThreadID As Long
Dim hWndOfApp As Long
Dim hSysInfo As SYSTEM_INFO
Dim lBassAddr As Long
Private Sub Command1_Click()
List2.Clear
Dim s() As Byte, n As Long, i As Long
lBassAddr = Text2.Text
n = Text3.Text
ReDim s(n - 1)
hWndOfApp = FindWindow(vbNullString, Text1.Text)
If hWndOfApp = 0 Then
    MsgBox "
无法找到该窗口"
    Exit Sub
End If
hThreadID = GetWindowThreadProcessId(hWndOfApp, hProcessID)
If hProcessID = 0 Then
    MsgBox "无法取得ProcessID"
    Exit Sub
End If
   
hProcess = OpenProcess(PROCESS_ALL_ACCESS _
, 0, hProcessID)

If hProcess = 0 Then
    MsgBox "无法开启该Process"
    Exit Sub
End If

ReadProcessMemory hProcess, ByVal lBassAddr, s(0), n, ByVal 0&
For i = 0 To n - 1
    List2.AddItem "地址:" &(i + lBassAddr) & "= " & s(i)
Next


CloseHandle hProcess
End Sub

Private Sub Command2_Click()
Dim s() As Byte, n As Long, i As Long
Dim Data1 As Byte, Data2 As Integer, Data4 As Long
lBassAddr = Text4.Text
If Option1(0).Value Then
    n = 1
    ReDim s(0)
    Data1 = Text5.Text
    CopyMemory s(0), Data1, n
ElseIf Option1(1).Value Then
    n = 2
    ReDim s(0 To 1)
    Data2 = Text5.Text
    CopyMemory s(0), Data2, n
ElseIf Option1(2).Value Then
    n = 4
    ReDim s(0 To 3)
    Data4 = Text5.Text
    CopyMemory s(0), Data4, n
End If

hWndOfApp = FindWindow(vbNullString, Text1.Text)
hThreadID = GetWindowThreadProcessId(hWndOfApp, hProcessID)
hProcess = OpenProcess(PROCESS_ALL_ACCESS _
, 0, hProcessID)
WriteProcessMemory hProcess, ByVal lBassAddr, s(0), n, ByVal 0&
CloseHandle hProcess
End Sub

Private Sub Form_Load()
GetSystemInfo hSysInfo '取得应用程序最小及最大寻址
Text2.Text =hSysInfo.lpMinimumApplicationAddress '应用程序最小寻址
Text4.Text =hSysInfo.lpMinimumApplicationAddress '应用程序最小寻址
Label5.Caption = "可用地址从" & hSysInfo.lpMinimumApplicationAddress & _
" 到 " &hSysInfo.lpMaximumApplicationAddress
End Sub




这个和市面上的游戏修改器还有点差距,其实就少了搜寻的功能,不过这并不难,我有空会再把他加上。




文件出处


Honey


整理时间

2001'9,8.



如何对应某程序内存使用状态

原文地址:http://sunh.hosp.ncku.edu.tw/~cww/html/q00519.html


说明


这个程序可以用来对映出某程序内存使用的情况,主要是使用 VirtualQueryEx这个API去对应每个内存区块,这个和数有4个参数
 hProcess
 
对应Process的Handle
   pAddress
       内存地址
   lpBuffer
       指向MEMORY_BASIC_INFORMATION结构的变量
   dwLength
      lpBuffer资料的大小
而MEMORY_BASIC_INFORMATION结构 这个程序用到的部分有
BaseAddress : 基地址
State : 配置状态
RegionSize : 区块大小
Protect : 属性 有 E,R,W(可执行,可读,可写)三种属性
其它部分可以参考MSDN上的说明
这个程序只有对应前端2GB的部分 如果要对应全部(4GB) 必须加上一点点进位的转换提示一下
对应后半部时 tmpBassAddr要减去(2147483648#+ 2147483648#)
然对应部分程序一样 除了跳出循环的If要改成tmpBassAddr>= 0 这样就行了 不过由于执行时间很长 如果有需要再自行修改 因为2GB后是系统区段 我就省略啦


程序


'----------------------------------------------------------------------------------------------
'
这个程序需要2个Text 和1个Command
' Text1 : 用来输入窗口的标题 要对映记事本 只要在此输入记事本
' Text2 : 用来输出结果
' 将Text2的ScrollBars属性设成3,MultiLine属性设成True
' ----------------------------------------------------------------------------------------------
Option Explicit
Private Type MEMORY_BASIC_INFORMATION
     BaseAddress As Long
     AllocationBase As Long
     AllocationProtect As Long
     RegionSize As Long
     State As Long
     Protect As Long
     lType As Long
End Type
Private Declare Function VirtualQueryEx Lib "kernel32" (ByValhProcess As Long, lpAddress As Any, lpBuffer As MEMORY_BASIC_INFORMATION, ByValdwLength 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 MEM_COMMIT = &H1000
Private Const MEM_FREE = &H10000
Private Const MEM_RESERVE = &H2000

Private Const PAGE_NOACCESS = &H1
Private Const PAGE_READONLY = &H2
Private Const PAGE_READWRITE = &H4
Private Const PAGE_WRITECOPY = &H8
Private Const PAGE_EXECUTE = &H10
Private Const PAGE_EXECUTE_READ = &H20
Private Const PAGE_EXECUTE_READWRITE = &H40
Private Const PAGE_EXECUTE_WRITECOPY = &H80
Private Const PAGE_GUARD = &H100
Private Const PAGE_NOCACHE = &H200

Private Const SEC_IMAGE = &H1000000
Private Const MEM_MAPPED = &H40000
Private Const MEM_PRIVATE = &H20000
Private Const MEM_IMAGE = SEC_IMAGE

Private Declare Function OpenProcess Lib "kernel32" (ByValdwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId AsLong) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject AsLong) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" _
(ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias"FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName AsString) As Long
Dim mbi As MEMORY_BASIC_INFORMATION
Dim sOPT As String

Private Sub Command1_Click()
Dim hwnd As Long, hProcessID As Long, hProcess As Long
Dim tmpBassAddr As Double, lBassAddr As Long
hwnd = FindWindow(vbNullString, Text1.Text)
Call GetWindowThreadProcessId(hwnd, hProcessID)
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, hProcessID)
sOPT = "Begin List Process Memory Usage" & vbCrLf
sOPT = sOPT & "Process ID:" & hProcessID & vbCrLf
sOPT = sOPT & "
地址" &Space(3) & "配置情况" & Space(3) &"属性" & Space(3) & "大小" & vbCrLf
Do While True
    sOPT = sOPT & Hex(tmpBassAddr) & Space(3)
    Call VirtualQueryEx(hProcess, ByVal lBassAddr, mbi,Len(mbi))
    Call PrintProperty '印出内存属性
    tmpBassAddr = mbi.BaseAddress
    tmpBassAddr = tmpBassAddr + mbi.RegionSize
    If tmpBassAddr > &H7FFFFFFF Then '预防溢位
        ExitDo
    End If
    lBassAddr = tmpBassAddr '对应下一笔
Loop
Text2.Text = sOPT
CloseHandle hProcess
End Sub

Private Sub Form_Load()
Text1.Text = Me.Caption
Text2.ScrollBars = 3
Text2.MultiLine = True
Command1.Caption = "列出内存使用状态"
End Sub
Private Sub PrintProperty()
Select Case mbi.State
    Case MEM_COMMIT
        sOPT = sOPT & "已配置"
    Case MEM_FREE
        sOPT = sOPT & "Free"
    Case MEM_RESERVE
        sOPT = sOPT & "保留"
    Case Else
        sOPT = sOPT & "不明"
End Select

sOPT = sOPT & Space(3)

Select Case mbi.Protect
    Case PAGE_NOACCESS
        sOPT = sOPT & "---"
    Case PAGE_READONLY
        sOPT = sOPT & "-R-"
    Case PAGE_READWRITE
        sOPT = sOPT & "-RW"
    Case PAGE_EXECUTE
        sOPT = sOPT & "E--"
    Case PAGE_EXECUTE_READ
        sOPT = sOPT & "ER-"
    Case PAGE_EXECUTE_READWRITE
        sOPT = sOPT & "ERW"
    Case PAGE_EXECUTE_WRITECOPY
        sOPT = sOPT & "ERW"
    Case PAGE_WRITECOPY
        sOPT = sOPT & "--W"
    Case PAGE_GUARD
        sOPT = sOPT & "G"
    Case PAGE_NOCACHE
        sOPT = sOPT & "---"
    Case Else
        sOPT = sOPT & "不明"
End Select
sOPT = sOPT & Space(3)
sOPT = sOPT & mbi.RegionSize \ 1024 & "KB" & vbCrLf
End Sub


文件出处


  Honey


整理时间

  2001'12,1.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

评分

参与人数 1人气 +1 收起 理由
msflexgrid + 1 汗一下,你发个总站的链接就行了,难道你想把

查看全部评分

本帖被以下淘专辑推荐:

 楼主| 发表于 2009-8-7 07:38:07 | 显示全部楼层
附件里的IMP文件是一种压缩文件格式,使用WinImp来打开
回复 支持 反对

使用道具 举报

发表于 2009-8-7 09:54:58 | 显示全部楼层
?是某大大??的用vb6
我不知道?可以用到那?~~~?如何用?~~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2022-7-4 04:33

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表