VBGood网站全文搜索 Google

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

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
查看: 3538|回复: 10

[转帖] 不调用任何API就能获得数组的SAFEARRAY地址

[复制链接]
发表于 2014-11-9 22:55:33 | 显示全部楼层 |阅读模式
RT,今天我无聊看Wikibooks的VB教程,结果看到这样一段话:
you can use the following hack to check if a dynamic array has been initialized:

  Dim MyArray() As String

  If (Not MyArray) = -1 Then   
    NumberOfElements = 0 'The array is uninitialised
  Else
    NumberOfElements = UBound(MyArray) + 1
  End If
  ReDim Preserve MyArray(0 To NumberOfElements) As String
  MyArray(UBound(MyArray)) = "my new friend"
我瞬间被老百姓吓死了  然后我自己测试了下
  1. Option Explicit

  2. Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (ByRef Ptr() As Any) As Long
  3. Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

  4. Private Sub Command1_Click()
  5. Dim s() As Long, i As Long
  6. ReDim s(5)
  7. Debug.Print Not Not s
  8. Debug.Print
  9. CopyMemory s(0), ByVal Not Not s, 24&
  10. For i = 0 To 5
  11.   Debug.Print s(i)
  12. Next i
  13. Debug.Print
  14. Debug.Print VarPtr(s(0))
  15. Debug.Print
  16. CopyMemory s(0), ByVal VarPtrArray(s), 4&
  17. Debug.Print s(0)
  18. End Sub
复制代码
结果显示
1794448

8388609
4
1
2068184
6
0

2068184

1794448
鉴定结论是Not s会把数组s的SAFEARRAY地址传输过去Not掉,所以再Not一次就变成SAFEARRAY地址了 妈妈再也不用叫我调用API了   看来我还是火星了,一直没发现这么可恶的方法

点评

@Jen 火星人,Not当然没有陷阱,Not和C/C++里面的~一样,VB里面没有!运算符  发表于 2014-11-10 17:10
Jen
好像有人研究过,Not有陷阱。  发表于 2014-11-10 08:10
dxs
赞一个,建议测试下效率,varptr vs not not  发表于 2014-11-10 05:47
叹服! not有点像函数的味道(现在正在看lisp,感觉啥像函数)  发表于 2014-11-9 23:13
发表于 2014-11-10 00:55:42 | 显示全部楼层
本帖最后由 bxc1995 于 2014-11-10 01:03 编辑

居然不发原文链接..帮你补上:https://en.wikibooks.org/wiki/Visual_Basic/Arrays
厉害啊.not操作符居然会暴露数组地址.
这算是设计缺陷吗?

点评

@huangshanvs 说Wikibooks被墙了  发表于 2014-11-10 17:11
测试了下,只有not可以,可能是因为它是一元运算符吧  发表于 2014-11-10 12:45
对了,你试试Or 0是不是也可以取数组地址,另外wb没被墙啊.  发表于 2014-11-10 12:36
这应该是隐藏功能,PS:原文链接忘了。。。话说有人跟我说Wikibooks被墙了,上不了,所以我就没法原文链接  发表于 2014-11-10 12:23
回复 支持 反对

使用道具 举报

头像被屏蔽
发表于 2014-11-10 01:07:00 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

发表于 2014-11-10 12:52:50 | 显示全部楼层
本帖最后由 bxc1995 于 2014-11-10 12:54 编辑

看到了jen说的关于not"陷阱"的文章了
http://fenying.blog.163.com/blog/static/1020559932009723114756474/
认为这不算陷阱,在汇编中,not本来就是按位取反吧.
至于文章中提及的
  1. If Not XXXXXX(....) Then '
复制代码
我很久不使用这种写法了,原来还一直不清楚是哪里的问题,现在算是明白了,因为True只有在VB中是全位都是1(有符号数即-1).
也就只有在VB中Not True = False.
而调用一些系统API或者C++写的函数的话,使用If Not就呵呵了.
把1按位取反,反正结果不是0~.

点评

那人太挫了,还无语呢,其实是他自己火星  发表于 2014-11-10 17:07
回复 支持 反对

使用道具 举报

发表于 2014-11-10 13:08:15 | 显示全部楼层
做了比较代码如下,陷阱也很明白.不能用not not 简单代替 varptr,但效率提高上百倍(编译后)或降低上百倍(IDE运行)
Option Explicit
Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Private Declare Function GetTickCount Lib "KERNEL32" () As Long
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Var() As Any) As Long
Private Sub Command1_Click()
Dim myarray() As Long, Count As Long
Count = 99999999

Dim tmptime As Long, i As Long, tmpptr As Long, arrayptr As Long
tmptime = GetTickCount
For i = 1 To Count
   tmpptr = Not Not myarray
Next
Print "未初始化Not耗时" & GetTickCount - tmptime & "毫秒", tmpptr

tmptime = GetTickCount
For i = 1 To Count
   tmpptr = VarPtrArray(myarray)
Next
CopyMemory arrayptr, ByVal tmpptr, 4
Print "未初始化VarPtrArray耗时" & GetTickCount - tmptime & "毫秒", tmpptr, arrayptr


ReDim myarray(10)

tmptime = GetTickCount
For i = 1 To Count
   tmpptr = Not Not myarray
Next
Print "已初始化Not耗时" & GetTickCount - tmptime & "毫秒", tmpptr

tmptime = GetTickCount
For i = 1 To Count
   tmpptr = VarPtrArray(myarray)
Next
CopyMemory arrayptr, ByVal tmpptr, 4
Print "已初始化VarPtrArray耗时" & GetTickCount - tmptime & "毫秒", tmpptr, arrayptr


End Sub

点评

Not Not myarray 不等于 VarPtrArray(myarray),而是等于 VarPtrArray(myarray)里面保存的数据  发表于 2014-11-10 17:05
回复 支持 反对

使用道具 举报

发表于 2014-11-10 17:57:47 | 显示全部楼层
Problems & Issues

There is one major problem: for whatever reason VB IDE does not like this method, and will raise an error in some cases, for example when floating point numbers are coerced to other datatypes. The error does not happen when the program is compiled.


http://www.vbforums.com/showthre ... wfull=1#post2272107

点评

好吧  发表于 2014-11-10 18:15
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-11-10 18:26:12 | 显示全部楼层


果然有问题
  1. Option Explicit

  2. Private Sub Command1_Click()
  3. Dim i As Long, j() As Long
  4. i = Not Not j
  5. i = 0.1
  6. End Sub
复制代码
然后在IDE里运行,在最后一句话报“表达式太复杂” 然后再点播放就又能运行了
回复 支持 反对

使用道具 举报

发表于 2014-11-11 15:16:42 | 显示全部楼层
本帖最后由 bxc1995 于 2014-11-11 15:26 编辑
acme_pjz 发表于 2014-11-10 18:26
果然有问题然后在IDE里运行,在最后一句话报“表达式太复杂” 然后再点播放就又能运行了: ...


测试了下,不仅这样不行.
写成这样也会在IDE模式报错
  1. Option Explicit

  2. Private Sub Command1_Click()
  3.   Dim i As Long, j() As Long

  4.   i = Not Not j
  5.   i = CLng(0.1)
  6. End Sub
复制代码
另外i只要赋值过Not Not j.不管中间有没有代码,i有没有被重新赋值,都会报错.
把j定义到全局也不行.并且全编译执行模式也一样.
这是为何?去掉或者注释掉i = Not Not j就好了.
按理说这不该影响下文啊?
并且在IDE模式下断言Not 一个数组 Or App.hInstance就可以干掉报错对话框了?
感觉这好像是无意造就的一个漏洞吧?

点评

。。。那要先找到IDE什么地方有问题  发表于 2014-11-11 20:39
话说patch掉ide怎么样0.0  发表于 2014-11-11 20:33
原来如此~  发表于 2014-11-11 20:32
IDE和这个不兼容造成的,估计是把浮点状态标志搞乱了  发表于 2014-11-11 20:31
回复 支持 反对

使用道具 举报

发表于 2014-11-11 21:05:28 | 显示全部楼层
本帖最后由 bxc1995 于 2014-11-11 21:07 编辑

正在分析.
大概找到弹窗口的位置了.但现在需要知道IDE在什么情况下应该正确的弹出实时错误 '16'的对话框.
关键点:
模块:VB6.EXE RVA:10144F
  1. 0050144F  |> \56            push    esi
  2. 00501450  |.  68 88115000   push    VB6.00501188
  3. 00501455  |.  68 B50F0000   push    0xFB5                            ;  对话框ID
  4. 0050145A  |.  FF35 4CB25900 push    dword ptr ds:[0x59B24C]          ;  VB6IDE.0F6F0000
  5. 00501460  |.  E8 AA0F0100   call    VB6.0051240F
复制代码
要压栈4个参数,第1个参数是对话框模板所在模块(VB6IDE.dll)的基址(即HINSTANCE).第2个参数是对话框ID.
第3个参数是个常量为00501188.第4个参数是个指针,暂不知到有什么用处.

点评

看看Not Not j编译成什么代码了  发表于 2014-11-11 21:50
往前面翻了好几个call,没有找到类似于触发错误的跳转.但是发现了在VB6内部的调试模式,程序是以PCODE方式执行的.  发表于 2014-11-11 21:24
。。。你改这个没用吧,应该看看什么地方触发错误了  发表于 2014-11-11 21:18
回复 支持 反对

使用道具 举报

发表于 2014-11-11 23:55:05 | 显示全部楼层
这个用法风骚至极啊!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2022-6-29 20:57

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