|

楼主 |
发表于 2012-2-6 20:01:02
|
显示全部楼层
本帖最后由 仙剑魔 于 2012-2-6 20:28 编辑
伪造数组并不难,难的是维护伪造出来的数据
直接声明dim temp as SAFEARRAY是不现实的,因为出了作用域就被释放了
HeapAlloc之类的固然可以,但是我不喜欢用太多API
于是就要用到开头的那个结论了
把数据存在字符串里,哈哈
vb的string其实存的也是个地址,地址位置的内容是一个BSTR结构,头部是4字节表示长度,后面跟着缓冲区
所以preserve的时候,VB没有去动BSTR的数据,而是直接拷贝了地址
代码如下:
使用方法
- Option Explicit
- Private Sub Form_Load()
- Dim a() As Long
- Dim b As Long
- Dim c() As Long
- Dim d As Long
- Call CallPtrProc(AddressOf SetPtrProc, a, VarPtr(b), LenB(b), &H7FFFFFFF)
- Call CallPtrProc(AddressOf SetPtrProc, c, VarPtr(d), LenB(d), &H7FFFFFFF)
- a(0) = 6
- Call CallPtrProc(AddressOf ClearPtrProc, a, 1)
- c(0) = 7
- Call CallPtrProc(AddressOf ClearPtrProc, c, 1)
- End Sub
复制代码 模块代码
- Option Explicit
- Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
- Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (dest As Any, ByVal numBytes As Long)
- Public Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Var() As Any) As Long
- 'Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
- Public Declare Function CallPtrProc Lib "user32" Alias "CallWindowProcA" (ByVal Func As Long, ByRef PPtr() As Any, Optional ByVal Param1 As Long = 0, Optional ByVal Param2 As Long = 0, Optional ByVal Param3 As Long = 0) As Long
- Private Type SAFEARRAY_KAI 'SAFEARRAY_改
- cDims As Integer '这个数组有几维?
- fFeature As Integer '这个数组有什么特性?
- cbElements As Long '数组的每个元素有多大?
- cLocks As Long '这个数组被锁定过几次?
- pvData As Long '这个数组里的数据放在什么地方?
- 'rgsabound() As SFArrayBOUND
- cElements As Long '这一维有多少个元素?
- lLbound As Long '它的索引从几开始?
-
- hHandle As Long
- End Type
- Private Buffer() As String
- Private Count As Long
- Public Sub SetPtrProc(ByVal PPtr As Long, _
- ByVal Address As Long, _
- Optional ByVal ElementSize As Long = 4, _
- Optional ByVal ElementCount As Long = &H7FFFFFFF)
- Dim SA As SAFEARRAY_KAI
- Count = Count + 1
- With SA
- .cDims = 1
- .fFeature = 0
- .cbElements = ElementSize
- .cLocks = 0
- .pvData = Address
- .cElements = ElementCount
- .lLbound = 0
- .hHandle = Count
- End With
- ReDim Preserve Buffer(0 To Count)
- Buffer(Count) = String(Len(SA) \ 2, 0)
- Call CopyMemory(ByVal StrPtr(Buffer(Count)), SA, Len(SA))
- Call CopyMemory(ByVal PPtr, StrPtr(Buffer(Count)), 4)
- End Sub
- Public Sub ClearPtrProc(ByVal PPtr As Long, _
- Optional ByVal RemoveAll As Long = 0, _
- Optional ByVal Reserve1 As Long = 0, _
- Optional ByVal Reserve2 As Long = 0)
- 'Debug.Print StrPtr(Buffer(1))
- Dim SA As SAFEARRAY_KAI
- Dim PSA As Long
- Dim i As Long
- Call CopyMemory(PSA, ByVal PPtr, 4)
- Call CopyMemory(SA, ByVal PSA, Len(SA))
- i = SA.hHandle
- Call CopyMemory(SA, ByVal StrPtr(Buffer(Count)), Len(SA))
- SA.hHandle = i
- Call CopyMemory(ByVal StrPtr(Buffer(Count)), SA, Len(SA))
- Call SwapString(Buffer(i), Buffer(Count))
- Count = Count - 1
- Call ZeroMemory(ByVal PPtr, 4)
-
- If RemoveAll Then
- 'Dim SA As SAFEARRAY_KAI
- 'Dim i As Long
- 'Dim Offset As Long
- 'Offset = VarPtr(SA.hHandle) - VarPtr(SA)
- 'For i = Count To 1 Step -1
- ' Call CopyMemory(SA, ByVal StrPtr(Buffer(i)), Len(SA))
- ' If SA.hHandle = PPtr Then
- ' Call SwapString(Buffer(i), Buffer(Count))
- ' Count = Count - 1
- ' End If
- 'Next
- ReDim Preserve Buffer(0 To Count)
- End If
- End Sub
- Public Sub IncPtrProc(ByVal PPtr As Long, _
- Optional ByVal Reserve1 As Long = 0, _
- Optional ByVal Reserve2 As Long = 0, _
- Optional ByVal Reserve3 As Long = 0)
- Dim SA As SAFEARRAY_KAI
- Dim PSA As Long
- Call CopyMemory(PSA, ByVal PPtr, 4)
- Call CopyMemory(SA, ByVal PSA, Len(SA))
- SA.pvData = SA.pvData + SA.cbElements
- Call CopyMemory(ByVal PSA, SA, Len(SA))
- End Sub
- Private Sub SwapString(ByRef s1 As String, ByRef s2 As String)
- Dim t As Long
- Call CopyMemory(t, ByVal VarPtr(s1), 4)
- Call CopyMemory(ByVal VarPtr(s1), ByVal VarPtr(s2), 4)
- Call CopyMemory(ByVal VarPtr(s2), t, 4)
- End Sub
复制代码 整合一个新结构SAFEARRAY_KAI,所有的数据都以他为模板
每次申请新指针,buffer的下标count都+1
释放时交换释放位置和末尾的string(其实换的是指针)
至于为什么用CallWindowProc ?
好吧,那是为了用any绕过类型检查。。。
PS:
IncPtrProc是把指针往后移...
ElementCount 用&h7fffffff是为了避免VB的数组越界检查,当然你也可以为了防止指针越界自己定个大小 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|