鲁迅的幽默故事:全球首创? 再次突破VB极限!VB真正稳定多线程(不用tlb,tls,ax,pcode)
来源:百度文库 编辑:九乡新闻网 时间:2024/05/06 10:13:22
本帖最后由 VBProFan 于 2010-4-29 16:21 编辑
全球首创? 全球再次突破VB极限!
只需在线程中加一行代码实现 VB 真正稳定多线程
不需要...
1.不需要写tlb库(感觉麻烦了,使用tlb主要是防止vb设置err.lastDllerr),
2.不需要处理tls(很多都是暴力copy,不知道有没有后遗症?)
3.不需要编译成activx exe(这东东会在注册表留下垃圾项,从VB的引用中会看到),
4.不需要编译成p-code(P代码的坏处众所周知了)
5.不需要干掉 setSysXXXerr(干掉后 err.lastDllErr肯定无效啦,不爽)
6.不需要远程创建线程...(汗,谁发明的,好厉害,转了好大一个圈)
...(还有没有?)
俗话说得好,有钱能使鬼推磨,果然不假...
此次的灵感来源于这1000块大洋...
http://www.vbgood.com/viewthread.php?tid=92649
(上面的代码是使用P CODE实现的VB线程安全)
等你学会了全球首创大法后,就能把他改为本机代码的线程安全.原代码不需要用TLB再次封装修改.
http://www.freevbcode.com/ShowCode.Asp?ID=4029
接下来.用上面"全球首创"的方法改进一下...
当然了,仍有不足之处,暂时不说(其实在别的贴子说过了),留给大家去发现...
未完待续...(根据反应的良好后再加以重点说明.反应不好的就不说明了 )
PS:有钱的记得加钱,没钱的记得加分啊~~~ 这样才会继续公开VB内幕...
PPS:如果是mei nv也可以向老汉使mei ren计,偶可是会中计滴...
-----------------------下面是揭密----------------------------
只需在线程中加一行代码实现 VB 真正稳定多线程揭密
1.为什么要声明成tlb库的原因.
众所周知,VB的函数包装了API,举例:
当调用GetProcAddr时,VB是用的DllCallFunction(好像是这个名吧?记不太清了)先检查有没有加载,有的话直接JMP过去,没有的话又要执行几个API进行加载. 同样的,当调用GetLastWin32Err(估计这是个名吧?记不太清)同样的,又是经过了几个API.这时的错误号己经不是最初的那个API的错误了.(可能己被覆盖) 那么API出错怎么知道呢,调用源码中声明的API的时候,VB就自作聪明的在后面加上一句SetXXXErr(全名记不太清).这样一来.当在多线程或回调中调用API时.变成了下面这样
DllCall MessageBox
SetXXXErr err.LastDllError (这个err是个对象,保存winapi.GetLastError的值,免得被VB函数中调用的API覆盖了错误信息)
在一般情况下是正常的,在线程中由于这个err没有初始化,所以就会保存错误号到未初始化的内存中.就出现线程错误了.
用TLB时VB编译后这个函数放到了PE头部的导入表中,调用时就不需要LoadLib,GetProcAddr,直接jmp 到导入表的地址即可(由PE的加载器填入)
这样就不会有VB中多余的API操作影响winapi.GetLastError的值了.所以VB又自作主张的去掉了SetXXXerr...这样线程中就正常了,当然(还是不能调用其它的VB函数(特别是和对象有关的)
这样一来,每个需要用的函数要用TLB声明一下,相当的麻烦.结果本来只需要写一行声明在源码中,变成了写到TLB的源文件I/ODL中,再用midl编译,还要再引用,最后才能使用...(这里己经讲到关键了,就不再废话了,不然pjz说我充字数骗稿费就不好了-_-!)
总之用TLB写VB函数不是给VB的程序员用的,是给VC+SDK这类程序员用...
例子:顶楼的声明去掉,改为TLB即成.
2.不需要处理tls(很多都是暴力copy,不知道有没有后遗症?)
不知道是谁发明的...好像是CSDN的超级绿豆?这种我看着晕,所以没测试...
例子:http://www.vbgood.com/viewthread.php?tid=88445
(VBProFan 注:iceboy 的 copy tls)
3.不需要编译成activx exe(这东东会在注册表留下垃圾项,从VB的引用中会看到),
这个我最早在国外发现...
由于和揭密无关,就不说了,简单说下,如果想取消注册表的项,可以 shell "filename.exe /unregserver"
例子: http://www.vbgood.com/viewthread.php?tid=65375
4.不需要编译成p-code(P代码的坏处众所周知了)
和揭密无关,为节省版面略之...(猜想由于PCODE在虚拟机中运行,所以VB的对象都是OK的,不会有什么大问题)
例子: 顶楼的那个国外的链接
5.不需要干掉 setSysXXXerr
头痛医头,脚头医脚的办法.
nop掉后也只能用VB内声明的API,还是无法用VB字符串之类的函数
6.不需要远程创建线程...
和揭密无关,略过
例子自己找吧: 好像是chenhui530的RtlCreateUserThread
最最关键来源于这里:
http://www.vbgood.com/viewthread.php?tid=88445
这段文字...
也就是说我们只有一次机会... -_-!
于是开始老汉猜想(不是哥德巴赫猜想)
1.那么最好的办法是什么?
2.为什么在VB的IDE中可以运行?
原因只有一点:就是VB中己经初始化了他需要的对象.
那么有没有初始化对象的这个未公开的函数呢?
于是开始追踪:
(过程可到看雪参观: http://bbs.pediy.com/showthread.php?threadid=36400)
仅贴关键思路点:
此时线程中的第二条API应该就是__vbaSetSystemError,也就是非TLB多线程的瓶颈,
这个时候己经没关系了,因为上面己经完成了初始化.至此揭密己经告一段落.为什么参数是0,4,0?
这个就不太清楚了,因为是无文档的东东...留给大家继续发现...
------------------------揭密完成-----------------------
全球首创? 全球再次突破VB极限!
只需在线程中加一行代码实现 VB 真正稳定多线程
不需要...
1.不需要写tlb库(感觉麻烦了,使用tlb主要是防止vb设置err.lastDllerr),
2.不需要处理tls(很多都是暴力copy,不知道有没有后遗症?)
3.不需要编译成activx exe(这东东会在注册表留下垃圾项,从VB的引用中会看到),
4.不需要编译成p-code(P代码的坏处众所周知了)
5.不需要干掉 setSysXXXerr(干掉后 err.lastDllErr肯定无效啦,不爽)
6.不需要远程创建线程...(汗,谁发明的,好厉害,转了好大一个圈)
...(还有没有?)
俗话说得好,有钱能使鬼推磨,果然不假...
此次的灵感来源于这1000块大洋...
http://www.vbgood.com/viewthread.php?tid=92649
(上面的代码是使用P CODE实现的VB线程安全)
等你学会了全球首创大法后,就能把他改为本机代码的线程安全.原代码不需要用TLB再次封装修改.
- '无文档的VB API
- Public Declare Function CreateIExprSrvObj Lib "msvbvm60.dll" (ByVal p1_0 As Long, ByVal p2_4 As Long, ByVal p3_0 As Long) As Long
- '调用方法:在线程函数的第一行加上
- CreateIExprSrvObj 0, 4, 0
http://www.freevbcode.com/ShowCode.Asp?ID=4029
接下来.用上面"全球首创"的方法改进一下...
- Public Sub test_function()
- CreateIExprSrvObj 0, 4, 0'加到线程函数的第一句
- Dim i As Long
- Dim ret As Long
- ...
- Public Sub test_function2()
- CreateIExprSrvObj 0, 4, 0'此例中共有2个线程,所以加2句,这是第2句
- msgbox "ok?" '测试 VB的提示框...(效果自己下载代码看)
- ''''
当然了,仍有不足之处,暂时不说(其实在别的贴子说过了),留给大家去发现...
未完待续...(根据反应的良好后再加以重点说明.反应不好的就不说明了 )
PS:有钱的记得加钱,没钱的记得加分啊~~~ 这样才会继续公开VB内幕...
PPS:如果是mei nv也可以向老汉使mei ren计,偶可是会中计滴...
-----------------------下面是揭密----------------------------
只需在线程中加一行代码实现 VB 真正稳定多线程揭密
1.为什么要声明成tlb库的原因.
众所周知,VB的函数包装了API,举例:
当调用GetProcAddr时,VB是用的DllCallFunction(好像是这个名吧?记不太清了)先检查有没有加载,有的话直接JMP过去,没有的话又要执行几个API进行加载. 同样的,当调用GetLastWin32Err(估计这是个名吧?记不太清)同样的,又是经过了几个API.这时的错误号己经不是最初的那个API的错误了.(可能己被覆盖) 那么API出错怎么知道呢,调用源码中声明的API的时候,VB就自作聪明的在后面加上一句SetXXXErr(全名记不太清).这样一来.当在多线程或回调中调用API时.变成了下面这样
DllCall MessageBox
SetXXXErr err.LastDllError (这个err是个对象,保存winapi.GetLastError的值,免得被VB函数中调用的API覆盖了错误信息)
在一般情况下是正常的,在线程中由于这个err没有初始化,所以就会保存错误号到未初始化的内存中.就出现线程错误了.
用TLB时VB编译后这个函数放到了PE头部的导入表中,调用时就不需要LoadLib,GetProcAddr,直接jmp 到导入表的地址即可(由PE的加载器填入)
这样就不会有VB中多余的API操作影响winapi.GetLastError的值了.所以VB又自作主张的去掉了SetXXXerr...这样线程中就正常了,当然(还是不能调用其它的VB函数(特别是和对象有关的)
这样一来,每个需要用的函数要用TLB声明一下,相当的麻烦.结果本来只需要写一行声明在源码中,变成了写到TLB的源文件I/ODL中,再用midl编译,还要再引用,最后才能使用...(这里己经讲到关键了,就不再废话了,不然pjz说我充字数骗稿费就不好了-_-!)
总之用TLB写VB函数不是给VB的程序员用的,是给VC+SDK这类程序员用...
例子:顶楼的声明去掉,改为TLB即成.
2.不需要处理tls(很多都是暴力copy,不知道有没有后遗症?)
不知道是谁发明的...好像是CSDN的超级绿豆?这种我看着晕,所以没测试...
例子:http://www.vbgood.com/viewthread.php?tid=88445
(VBProFan 注:iceboy 的 copy tls)
3.不需要编译成activx exe(这东东会在注册表留下垃圾项,从VB的引用中会看到),
这个我最早在国外发现...
由于和揭密无关,就不说了,简单说下,如果想取消注册表的项,可以 shell "filename.exe /unregserver"
例子: http://www.vbgood.com/viewthread.php?tid=65375
4.不需要编译成p-code(P代码的坏处众所周知了)
和揭密无关,为节省版面略之...(猜想由于PCODE在虚拟机中运行,所以VB的对象都是OK的,不会有什么大问题)
例子: 顶楼的那个国外的链接
5.不需要干掉 setSysXXXerr
头痛医头,脚头医脚的办法.
nop掉后也只能用VB内声明的API,还是无法用VB字符串之类的函数
6.不需要远程创建线程...
和揭密无关,略过
例子自己找吧: 好像是chenhui530的RtlCreateUserThread
最最关键来源于这里:
http://www.vbgood.com/viewthread.php?tid=88445
这段文字...
需要说明的是在线程函数里面,只有一次调用API的机会~
因为VB编译器会在每个API后面添加__vbaSetSystemError,
如果未经处理__vbaSetSystemError是肯定会出错的...(后面还有一些,和主题无关略之)
也就是说我们只有一次机会... -_-!
于是开始老汉猜想(不是哥德巴赫猜想)
1.那么最好的办法是什么?
2.为什么在VB的IDE中可以运行?
原因只有一点:就是VB中己经初始化了他需要的对象.
那么有没有初始化对象的这个未公开的函数呢?
于是开始追踪:
(过程可到看雪参观: http://bbs.pediy.com/showthread.php?threadid=36400)
仅贴关键思路点:
- OD自动反汇编了这个有问题的KEYGEN。我们逐步跟踪,到下面的代码时,出现异常,问题就出在__vbaStrCat中。
- 004012BC . E8 2B020000 CALL
- 我们跟入__vbaStrCat:
- ...
- 660E5F47 FF15 18EE1066 CALL DWORD PTR DS:[6610EE18] ; DS:[6610EE18]=00000000,问题出在这里
- ...
- 跟到660E5F47时出现异常,我们看到PTR DS:[6610EE18]为0,我们拿原来的CRACKME或者直接拿msvbvm60.dll反汇编,跟入__vbaStrCat:
- 660E5F47 FF15 18EE1066 CALL DWORD PTR DS:[6610EE18] ; OLEAUT32.VarBstrCat
- 可以看出问题所在:PTR DS:[6610EE18]在CRACKEME中有被初始化成VarBstrCat而在KEYGEN中没有。
- 我们跟入__vbaStrCat:
- text:66004D81 ; CreateIExprSrvObj+3E p
- CreateIExprSrvObj觉得可疑,跟进看看:
- .text:660EA734 public CreateIExprSrvObj
- .text:660EA734 CreateIExprSrvObj proc near
- ...
- .text:660EA772 call sub_66004D81 <---- 就是这个CALL
- 我们需要这个CALL,deroko对CALL进行了修改并使之运行正常:
- push 0
- push 4
- push 0
- call CreateIExprSrvObj(记得改call为cinvoke)
- ...
- '无文档的VB API
- Public Declare Function CreateIExprSrvObj Lib "msvbvm60.dll" (ByVal p1_0 As Long, ByVal p2_4 As Long, ByVal p3_0 As Long) As Long
- '调用方法:在线程函数的第一行加上
- CreateIExprSrvObj 0, 4, 0
此时线程中的第二条API应该就是__vbaSetSystemError,也就是非TLB多线程的瓶颈,
这个时候己经没关系了,因为上面己经完成了初始化.至此揭密己经告一段落.为什么参数是0,4,0?
这个就不太清楚了,因为是无文档的东东...留给大家继续发现...
------------------------揭密完成-----------------------