Board logo

标题: vb问题(3) [打印本页]

作者: 阿尔法孝直    时间: 2008-6-10 15:52     标题: vb问题(3)

请看下面一段程序:

(声明API函数部分省略。。。)
Private Sub Command1_Click()
Dim i As Byte , Data As Byte , MyStr As String*1
For i=0 To 255
Data=i
WriteProcessMemory MyProcess, Address, Data, 1, 0&
ReadProcessMemory MyProcess, Address, MyStr, 1, 0&
Data=Asc(MyStr)
Debug.Print Data
Next i
End Sub

问题是,程序运行后,显示如下结果:

QUOTE:
0
1
2
3
4
5
中间省略……
124
125
126
127
0
0
0
中间省略……
0
0
0

现在我希望0~255的数据都能从内存读出来,如下:

QUOTE:
1
2
3
4
5
中间省略……
251
252
253
254
255

问应该如何修改程序???
作者: 土狼    时间: 2008-6-10 16:20

不能肯定问题出在哪,感觉是读写过程中出了错

个人建议楼主不要用byte这种类型,大大方方的用integer,不在乎那点内存吧
作者: 阿尔法孝直    时间: 2008-6-10 16:23

没用,这个是ASCII编码问题,用Integer就更不行了。
作者: 司徒苍月    时间: 2008-6-10 17:13

ASCII编码7+1位校验,所以只能是2的7次方
作者: Maxwell    时间: 2008-6-10 18:09

机器上没有VB,晚上回去没有网络,明天再看。。。
作者: Maxwell    时间: 2008-6-11 10:40

昨天没时间试,简单猜测一下吧。

[Copy to clipboard]
CODE:
Private Sub Command1_Click()
    Dim i As Byte , Data As Byte , MyStr As String*1

    For i=0 To 255
        Data=i
        WriteProcessMemory MyProcess, Address, Data, 1, 0&
        ReadProcessMemory MyProcess, Address, MyStr, 1, 0&
        Data=Asc(MyStr)
        Debug.Print Data
    Next i
End Sub

首先i不应该定义为byte类型,不然循环会溢出。
MyStr应该是个引用,所以把MyStr的地址传给ReadProcessMemory恐怕会有问题,不过你前127个倒是显示出来了,估计还是跟String内部实现机制有关,String内部可能是unicode存储的,对高于127的字符需要特别处理,这个仅是猜测,但是MSDN中对String的描述中有一条就是不要用于任何跟数值有关的地方。你用另外一个byte类型的变量传给ReadProcessMemory不行吗?
作者: Maxwell    时间: 2008-6-11 10:41



QUOTE:
原帖由 司徒苍月 于 2008-6-10 17:13 发表
ASCII编码7+1位校验,所以只能是2的7次方


作者: 阿尔法孝直    时间: 2008-6-11 14:30

现在问题是怎么解决,我要搞一个内存修改器
作者: fantasydog    时间: 2008-6-11 14:48

不了解VB。
不过Byte是unsigned char么?
Asc这个函数返回值又是啥?unsigned char?

有符号的东西其实蛮讨厌的,移位都移不动
作者: Maxwell    时间: 2008-6-11 14:58



QUOTE:
原帖由 阿尔法孝直 于 2008-6-11 14:30 发表
现在问题是怎么解决,我要搞一个内存修改器

你用另外一个byte类型的变量传给ReadProcessMemory不行吗?

二进制这事儿VB确实不太擅长,有这功夫都可以学学其他语言了,当然仅供参考,当前还是先解决问题为主。
作者: Maxwell    时间: 2008-6-11 14:59



QUOTE:
原帖由 fantasydog 于 2008-6-11 14:48 发表
不了解VB。
不过Byte是unsigned char么?
Asc这个函数返回值又是啥?unsigned char?

有符号的东西其实蛮讨厌的,移位都移不动

移位移不动是不是因为是const类型的?
作者: 阿尔法孝直    时间: 2008-6-11 15:34



QUOTE:
原帖由 Maxwell 于 2008-6-11 14:58 发表


你用另外一个byte类型的变量传给ReadProcessMemory不行吗?

二进制这事儿VB确实不太擅长,有这功夫都可以学学其他语言了,当然仅供参考,当前还是先解决问题为主。

不行,好早就试过,会出错。
作者: Maxwell    时间: 2008-6-11 16:14



QUOTE:
原帖由 阿尔法孝直 于 2008-6-11 15:34 发表


不行,好早就试过,会出错。

查了一下第3个参数是ByVal lpBuffer As Any,这是byte不行的原因,另外string是用BSTR实现的,所以对于大于127的值可能有特别处理。
你贴一个能运行的代码吧,现在想了几个方案,不知道哪个能用,回头我试试。
作者: 龙王    时间: 2008-6-13 16:55

这里要用字符串数组,byte变量不行的,用VC++吧,用1个char 数组,然后CString
作者: 阿尔法孝直    时间: 2008-6-13 18:22

Sorry,VC++我不熟。
作者: Maxwell    时间: 2008-6-14 01:29

我是说你先贴一段能运行但是结果不正确的代码,然后我好试试怎么能用,不要让我自己补全代码了。
作者: fantasydog    时间: 2008-6-17 13:57     标题: 回复 #11 Maxwell 的帖子

不是,编译器直接报错。
就是不能移signed类型的,毕竟有个符号位在那里,处理起来相当麻烦。
我估计是编译器图省事,直接不准移位有符号数了。
再者,有符号数的移位通常意义也不大。乘除2的幂次的情况本来就少,也提高不了多少性能。
作者: Maxwell    时间: 2008-6-17 14:34

晕,什么语言?c#?从来没觉得c/c++中有不能移位的,就连浮点型真想移都能移了。到了机器码那一级,有没有符号位处理上都基本一样。
作者: 阿尔法孝直    时间: 2008-6-20 15:51

代码贴上来,大家看看。
顺便帮忙解决一下数据写不进内存的问题。

[ 本帖最后由 阿尔法孝直 于 2008-6-20 15:55 编辑 ]

附件: [简易内存读写器的代码] RWMemory.rar (2008-6-20 15:55, 2.86 K) / 该附件被下载次数 117
http://xycq.org.cn/forum/attachment.php?aid=62933
作者: Maxwell    时间: 2008-6-20 16:39

晕,到底是写不进去还是读不出来?哪个文件的哪个函数哪一行有问题,这样说明一下是不是更利于找问题?
作者: 阿尔法孝直    时间: 2008-6-20 16:55

第一个问题:

写内存的程序段:
  Private Sub Command3_Click()
   WriteProcessMemory nHandle, nAddress, CLng(Text2.Text), nByte, 0&
  End Sub
就红色这句,改个数执行之后再按“读取”,又变成原来的数。


第二个问题:

读内存的程序段:
  Private Sub Command1_Click()
    On Error Resume Next
    Dim nStr As String * 1
    Dim Result As Long
    Dim i As Byte
    For
i = 0 To nByte - 1
     ReadProcessMemory nHandle, nAddress + i, nStr, 1, 0&
     Result = Result + Asc(nStr) * 256 ^ i
    Next i
    Text2.Text = Trim(Str(Result))
  End Sub
就红色的这两句,第一句执行时,凡是任何单字节在128~255之间的数据,读出来都是0,即
  Asc(nStr)=0
作者: Maxwell    时间: 2008-6-20 17:04

知道了,周末有事,下周来看看。
作者: 阿尔法孝直    时间: 2008-6-23 17:46

第一个问题自己改了代码后,解决了。


现在剩下第二个问题:

读内存的程序段:
  Private Sub Command1_Click()
    On Error Resume Next
    Dim nStr As String * 1
    Dim Result As Long
    Dim i As Byte
    For
i = 0 To nByte - 1
     ReadProcessMemory nHandle, nAddress + i, nStr, 1, 0&
     Result = Result + Asc(nStr) * 256 ^ i
    Next i
    Text2.Text = Trim(Str(Result))
  End Sub
就红色的这两句,第一句执行时,凡是任何单字节在128~255之间的数据,读出来都是0,即
  Asc(nStr)=0

附件: RWMemory.rar (2008-6-23 17:46, 2.98 K) / 该附件被下载次数 101
http://xycq.org.cn/forum/attachment.php?aid=63031
作者: Maxwell    时间: 2008-6-24 10:52

想必楼主找到了一个可以写入的地址,不过我没有找到,我选择内存读写器,随机设置了几个地址写入都不成功。
作者: 阿尔法孝直    时间: 2008-6-24 11:20

随便打开一个游戏,比如曹操传,找到曹操的HP地址,看看行不行
作者: Maxwell    时间: 2008-6-24 14:28

好容易想了个办法测试了一下代码,有两种方法能够正确执行,有一种多少有点hack,说一下另一种吧,用下面的代码可以实现原来想要的功能,其实这里面还是利用了x86特性将byte, word, dword用一行代码处理了。VarPtr是一个内置函数,用于取变量的地址,相当于c/c++中的单目运算符&。
Private Sub Command1_Click()
    On Error Resume Next

    Dim data As Long

    ReadProcessMemory nHandle, nAddress, VarPtr(data), nByte, 0&

    Text2.Text = Trim$(Str$(data))
End Sub

你说写已经没问题那我就不测了,我怕写进去我的程序崩掉,参考这个代码相信也能用一行解决问题。
作者: 阿尔法孝直    时间: 2008-6-24 16:42

没用,还是一样。
不过前面的情况有错,应该是:

128~254还是0,
0~127或255正常读出。

[ 本帖最后由 阿尔法孝直 于 2008-6-24 16:51 编辑 ]
作者: Maxwell    时间: 2008-6-24 16:54

你在什么环境下测试的?如果255能读出来不可能128-254读不了
我测试的时候是读取自身进程的连续16个字节,其中有90,3,255,177,240。
作者: 阿尔法孝直    时间: 2008-6-24 17:18



QUOTE:
原帖由 Maxwell 于 2008-6-24 16:54 发表
你在什么环境下测试的?如果255能读出来不可能128-254读不了
我测试的时候是读取自身进程的连续16个字节,其中有90,3,255,177,240。

在XP SP2下用VB6按F5直接运行程序

我写一个字节再读出来

确实不行

不过情况又有变化:变成0~128或255能读,129~254不能读
作者: Maxwell    时间: 2008-6-24 17:24

你写的字节有没有写进去是个问题,所以我直接找一段地址挨着读,我后来试了一下,对于我测试的地址用你的代码写不进去。
作者: 阿尔法孝直    时间: 2008-6-24 17:53

金山游侠V检验的结果:
129~254能写进去,不过用金山游侠V读出来是0
内存数据是129~254,读出来是0
0~128或255读写都正常。
作者: Maxwell    时间: 2008-6-24 17:59

金山游侠读出来是0怎么知道是写进去了?我觉得用string有它天然的缺陷,内部是BSTR,当byte用很难说会出什么问题。
作者: 阿尔法孝直    时间: 2008-6-24 18:02



QUOTE:
原帖由 Maxwell 于 2008-6-24 17:59 发表
金山游侠读出来是0怎么知道是写进去了?

执行后,数据由非0变为0,说明写进去了。
作者: Maxwell    时间: 2008-6-24 18:12

你是说写进去之后在被写的程序里数值变了,而金山游侠读出来的也是0?那是不是因为程序又重新刷回了0,找个别的程序写写试试。
作者: 阿尔法孝直    时间: 2008-6-24 18:22

不会。因为我用0~128或255时没出现这种问题,且换了其他程序也是一样。
作者: Maxwell    时间: 2008-6-24 20:00

那你读一段现有非0数据,看看有没有落在这个范围内的,根据推测,问题不在代码上。
作者: 阿尔法孝直    时间: 2008-6-24 21:43

我试过,在0~128或255完全正常,没有任何问题
作者: Maxwell    时间: 2008-6-24 21:59

既然试过没有问题那就不是读取代码的问题了,读取代码从机制上没有特殊处理过。建议找个记事本读读数据试试,游戏里面的不确定性比较多。
作者: 阿尔法孝直    时间: 2008-6-24 22:29

记事本MS是只读进程,写进去什么,读出来都是原来的值。
不过可完全访问的进程都是0~128或255读写正常。
作者: Maxwell    时间: 2008-6-25 08:30

我的意思是从记事本里读连续100个位置,看看有没有在129-254之间的数字。或者读内存读写器试试,0x00400001-0x00400010之间有几个数。
作者: 阿尔法孝直    时间: 2008-6-25 10:40

这是我用金山游侠读取“记事本”进程十六进制0x1000040~0x100008F(十进制16777280~16777359)连续80个字节的结果(十六进制
红色为0x81~0xFE(十进制129~254)
0E
1F
BA
0E
00
B4
09
CD
21
B8
01
4C
CD
21
54
68
69
73
20
70
72
6F
67
72
61
6D
20
63
61
6E
6E
6F
74
20
62
65
20
72
75
6E
20
69
6E
20
44
4F
53
20
6D
6F
64
65
2E
0D
0D
0A
24
00
00
00
00
00
00
00
EC
85
5B
A1
A8
E4
35
F2
A8
E4
35
F2
A8
E4
35
F2

这是我用内存读写器读取“记事本”进程十进制16777280~16777359(十六进制0x1000040~0x100008F)连续80个字节的结果(十进制
14
31
0
14
0
0
9
0
33
0
1
76
0
33
84
104
105
115
32
112
114
111
103
114
97
109
32
99
97
110
110
111
116
32
98
101
32
114
117
110
32
105
110
32
68
79
83
32
109
111
100
101
46
13
13
10
36
0
0
0
0
0
0
0
0
0
91
0
0
0
53
0
0
0
53
0
0
0
53
0

作者: Maxwell    时间: 2008-6-25 11:54

我测试了前3个红字的值,都与你提供的金山游侠的值相同。
我的系统win2003serversp2 vb6sp6,使用下面的读取代码
Private Sub Command1_Click()
    On Error Resume Next

    Dim data As Long

    ReadProcessMemory nHandle, nAddress, VarPtr(data), nByte, 0&

    Text2.Text = Trim$(Str$(data))
End Sub




欢迎光临 轩辕春秋文化论坛 (http://xycq.org.cn/forum/) Powered by Discuz! 5.0.0