今天可是个好日子啊~~就在这个好日子送给我们广大的程序大朋友们和小朋友们一个节日礼物,同时我也希望这份代码能给带来一些思路和技术上的提升,但是更希望大家能用到正途上不要搞歪门邪道。此代码的功能比较强悍,所以用到好的地方自然能发光,但是用到黑暗的地方可能会辱没了这份代码,希望大家认真对待这份珍贵的代码,我是专门花了一天时间写的,而且专门用VB语言写的,其实用C的话更简单更快,就是想在节日送给我们广大的VB爱好者一个节日礼物。在这里祝大家“节日快乐”~哈哈~~想了很久也不知道怎么为这份代码(文章)取个好听的名字想来想去好像“移花接木”最适合。为什么这么说呢?这份代码可以完成远程调用,可以在远程进程中执行任何STDCALL声明的API函数,这样做到了“远程调用本地化”当然还没达到这种级别的效果,但是确实还是值得我们继续在这份代码上发展和研究。我在测试程序中写了三个典型的实例。首先是一个在远程进程中弹出一个消息框的测试(这里要保证目标进程已经加载了USER33.DLL才行)。第二个实例是演示了利用远程进程创建新进程的功能(在这里我想说点废话,我在我博客也发表了好几种创建SYSTEM进程的代码,当然有参考别人的代码和思路,以前也有人说过用远程注入的方式实现,但是好像是需要DLL的好了现在这份代码不再需要DLL而且你可以创建指定用户的进程,比如你可以创建SYSTEM用户甚至是LOAL SYSTEM用户等)。第三个实例是演示了NT系列函数的调用也是演示了参数带返回值的API函数在我的程序中的调用方法和取返回值的方法。其实还有很多很多的功能有待大家去研究琢磨我只是提供了一个小小的“平台”,希望大家在这个“平台”给你带来更多的精细也希望能使大家更深入的了解VB内嵌汇编的方法和需要注意些什么。我在这份代码上做了详细的注释,如果你在使用还有不明白的地方或者发现存在了某些BUG请于我一起探讨,谢谢。好了废话就不多说了大家等得都是代码。由于篇幅所限我只把关键部分代码贴在这如果想察看完整代码的请到我的博客去浏览。地址是:http://blog.csdn.net/chenhui530/archive/2008/06/01/2500112.aspx''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'参数Params是可变参数其中第一个参数为你写的SHELLCODE Buffer的地址,第二个参数是这个
'SHELLCODE Buffer的长度,第三个参数是API参数个数,从第四个参数起每3个参数形成API函
'数中的一个参数,其中第一个参数表明是否需要申请内存,第二个参数是值(这里如果需要申
'请内存的话这个值将是你需要)写入目标进程的Buffer所在你的进程空间的地址,第三个参数
'是Buffer长度(如果不需要申请内存的这个值可以填0因为默认是以&H68来Push参数的都是4个
'字节对齐,以后的API参数都是一样依次类推下去。直到API参数都完了后就是CALL的机器码E8
'接着是CallValue这个需要计算(我的程序会自动计算),后面紧接着是return 10h,然后再
'填个0好让CPU不要识别错了,因为可能你写到的地方最后一个字节不为0这样return值就会出错
'造成栈不平,参数pOutData为后加上去的主要是用来返回有些API的参数需要返回值的情况下,用
'发很简单传个数组进来即可然后返回的只是一个4个字节数据就保存在它的dwDataSize中,如果
'大于4个字节那么dwAddress是目标进程的数据所在地址dwDataSize是数据的长度,如果我们需要
'把这部分数据读出来只需要再次用ReadProcessMemory读取一次,如果有多个参数就遍历下数组
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function CallAsmFun(ByVal dwProcessId As Long, pOutData() As OUT_DAT, ParamArray Params()) As Long
'lplpRemoteAddress 是在目标进程为ShellCode申请的内存块地址,lpRemoteAddresses()是一些参数申请的内存快地址
'一般只有传结构或者是字符串的时候才需要
Dim lpRemoteAddress As Long, lpRemoteAddresses() As Long, intCount As Integer '在目标进程申请的内存计数
Dim hProcess As Long '进程句柄
Dim lngRet As Long '返回的结果
Dim hThread As Long, dwThreadId As Long '创建的选择线程句柄和TID
Dim i As Integer, j As Integer
Dim dwValue As Long, dwAddress As Long '值和地址
Dim intAgsCount As Integer '参数个数
Dim intOutCount As Integer
Dim blnIsFind As Boolean
'打开目标进程
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwProcessId)
If hProcess Then
'在目标进程申请一块内存,长度是SHELLCODE的长度,好把SHELLCODE写进去
lpRemoteAddress = VirtualAllocEx(hProcess, ByVal 0&, CLng(Params(1)), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
If lpRemoteAddress Then
dwAddress = CLng(Params(0)) '我们进程中SHELLCODE的地址
'把我们生成的SHELLCODE写入目标进程中
If WriteProcessMemory(hProcess, ByVal lpRemoteAddress, ByVal dwAddress, CLng(Params(i + 1)), ByVal 0) Then
'获取需要申请内存的参数计数
For i = Val(Params(2)) * 3 To 3 Step -3
If Val(Params(i)) = 1 Then
intCount = intCount + 1
End If
Next
If intCount > 0 Then
ReDim lpRemoteAddresses(intCount - 1) '申请保存参数申请内存的地址方便后面释放
End If
intCount = 0
intAgsCount = CLng(Params(2)) '我们传进来的第二个参数是API函数的参数个数
For i = intAgsCount * 3 To 3 Step -3 '从最后一个API参数开始取
If Val(Params(i)) = 1 Then
'如果是需要申请内存的参数(比如字符串或者结构等)我们就再申请一块内存
lpRemoteAddresses(intCount) = VirtualAllocEx(hProcess, ByVal 0&, CLng(Params(i + 2)), MEM_COMMIT, PAGE_READWRITE)
'把我们进程空间的才参数内存写入目标进程我们申请的内存块中
If CLng(Params(i + 1)) <> 0 Then
lngRet = WriteProcessMemory(hProcess, ByVal lpRemoteAddresses(intCount), ByVal CLng(Params(i + 1)), CLng(Params(i + 2)), ByVal 0)
If lngRet = 0 Then GoTo RET
Else
ReDim Preserve pOutData(0 To intOutCount)
pOutData(intOutCount).dwAddress = lpRemoteAddresses(intCount)
pOutData(intOutCount).dwDataSize = CLng(Params(i + 2))
intOutCount = intOutCount + 1
End If
'因为是__stdcall所以最前面的参数应该是在最后面相反最前面的在最后面
dwAddress = lpRemoteAddress + 4 + 5 * (intAgsCount - (i / 3)) + 1
'更改SHELLCODE里的push值,因为开始我们传进来的是我们的进程空间的地址,现在我们要替换成目标进程空间的地址
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, lpRemoteAddresses(intCount), 4, ByVal 0)
If lngRet = 0 Then GoTo RET
intCount = intCount + 1
Else
'如果参数不需要申请内存就直接写入值即可
dwAddress = lpRemoteAddress + 4 + 5 * (intAgsCount - (i / 3)) + 1
dwValue = Params(i + 1)
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, dwValue, 4, ByVal 0)
If lngRet = 0 Then GoTo RET
End If
Next
End If
'计算E8 XXXXXXXX中的XXXXXXXX所在目标进程空间中的地址
dwAddress = lpRemoteAddress + intAgsCount * 5 + 4 + 1
'获取函数的真正地址
CopyMemory dwValue, ByVal CLng(Params(0)), 4
'计算 XXXXXXXX的地址
dwValue = dwValue - (lpRemoteAddress + intAgsCount * 5 + 4) - 5
'更新E8后的XXXXXXXX值这样才能正确执行函数
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, dwValue, 4, ByVal 0)
If lngRet = 0 Then GoTo RET
'创建远程线程执行我们的SHELLCODE,这里我们可以换成Debug的Api比如SetThreadContext和QueueAPC之类的函数也行
hThread = CreateRemoteThread(hProcess, ByVal 0, 0, ByVal lpRemoteAddress + 4, ByVal 0, 0, dwThreadId)
If hThread Then
'等待线程执行结束
WaitForSingleObject hThread, INFINITE
For i = 0 To intOutCount - 1
If pOutData(i).dwDataSize = 4 Then
ReadProcessMemory hProcess, ByVal pOutData(i).dwAddress, pOutData(i).dwDataSize, 4, ByVal 0&
End If
Next
'获取返回值
GetExitCodeThread hThread, lngRet
End If
End If
End If
RET:
'清理我们申请的内存和关闭相关句柄
If hProcess Then
For i = 0 To intCount - 1
If intOutCount = 0 Then
VirtualFreeEx hProcess, ByVal lpRemoteAddresses(i), 0, MEM_RELEASE
Else
For j = 0 To intOutCount - 1
If lpRemoteAddresses(i) = pOutData(j).dwAddress Then
blnIsFind = True
Exit For
End If
Next
If Not blnIsFind Then VirtualFreeEx hProcess, ByVal lpRemoteAddresses(i), 0, MEM_RELEASE
End If
Next
If lpRemoteAddress Then VirtualFreeEx hProcess, ByVal lpRemoteAddress, 0, MEM_RELEASE
End If
If hProcess Then CloseHandle hProcess
If hThread Then CloseHandle hThread
CallAsmFun = lngRet
End Function'获取API函数的地址
Public Function GetFunAddress(ByVal strLibName As String, ByVal strFunName As String) As Long
Dim hMod As Long, dwFunAddress As Long
hMod = LoadLibrary(strLibName)
If hMod Then
dwFunAddress = GetProcAddress(hMod, strFunName)
End If
FreeLibrary hMod
GetFunAddress = dwFunAddress
End Function
'参数Params是可变参数其中第一个参数为你写的SHELLCODE Buffer的地址,第二个参数是这个
'SHELLCODE Buffer的长度,第三个参数是API参数个数,从第四个参数起每3个参数形成API函
'数中的一个参数,其中第一个参数表明是否需要申请内存,第二个参数是值(这里如果需要申
'请内存的话这个值将是你需要)写入目标进程的Buffer所在你的进程空间的地址,第三个参数
'是Buffer长度(如果不需要申请内存的这个值可以填0因为默认是以&H68来Push参数的都是4个
'字节对齐,以后的API参数都是一样依次类推下去。直到API参数都完了后就是CALL的机器码E8
'接着是CallValue这个需要计算(我的程序会自动计算),后面紧接着是return 10h,然后再
'填个0好让CPU不要识别错了,因为可能你写到的地方最后一个字节不为0这样return值就会出错
'造成栈不平,参数pOutData为后加上去的主要是用来返回有些API的参数需要返回值的情况下,用
'发很简单传个数组进来即可然后返回的只是一个4个字节数据就保存在它的dwDataSize中,如果
'大于4个字节那么dwAddress是目标进程的数据所在地址dwDataSize是数据的长度,如果我们需要
'把这部分数据读出来只需要再次用ReadProcessMemory读取一次,如果有多个参数就遍历下数组
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function CallAsmFun(ByVal dwProcessId As Long, pOutData() As OUT_DAT, ParamArray Params()) As Long
'lplpRemoteAddress 是在目标进程为ShellCode申请的内存块地址,lpRemoteAddresses()是一些参数申请的内存快地址
'一般只有传结构或者是字符串的时候才需要
Dim lpRemoteAddress As Long, lpRemoteAddresses() As Long, intCount As Integer '在目标进程申请的内存计数
Dim hProcess As Long '进程句柄
Dim lngRet As Long '返回的结果
Dim hThread As Long, dwThreadId As Long '创建的选择线程句柄和TID
Dim i As Integer, j As Integer
Dim dwValue As Long, dwAddress As Long '值和地址
Dim intAgsCount As Integer '参数个数
Dim intOutCount As Integer
Dim blnIsFind As Boolean
'打开目标进程
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwProcessId)
If hProcess Then
'在目标进程申请一块内存,长度是SHELLCODE的长度,好把SHELLCODE写进去
lpRemoteAddress = VirtualAllocEx(hProcess, ByVal 0&, CLng(Params(1)), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
If lpRemoteAddress Then
dwAddress = CLng(Params(0)) '我们进程中SHELLCODE的地址
'把我们生成的SHELLCODE写入目标进程中
If WriteProcessMemory(hProcess, ByVal lpRemoteAddress, ByVal dwAddress, CLng(Params(i + 1)), ByVal 0) Then
'获取需要申请内存的参数计数
For i = Val(Params(2)) * 3 To 3 Step -3
If Val(Params(i)) = 1 Then
intCount = intCount + 1
End If
Next
If intCount > 0 Then
ReDim lpRemoteAddresses(intCount - 1) '申请保存参数申请内存的地址方便后面释放
End If
intCount = 0
intAgsCount = CLng(Params(2)) '我们传进来的第二个参数是API函数的参数个数
For i = intAgsCount * 3 To 3 Step -3 '从最后一个API参数开始取
If Val(Params(i)) = 1 Then
'如果是需要申请内存的参数(比如字符串或者结构等)我们就再申请一块内存
lpRemoteAddresses(intCount) = VirtualAllocEx(hProcess, ByVal 0&, CLng(Params(i + 2)), MEM_COMMIT, PAGE_READWRITE)
'把我们进程空间的才参数内存写入目标进程我们申请的内存块中
If CLng(Params(i + 1)) <> 0 Then
lngRet = WriteProcessMemory(hProcess, ByVal lpRemoteAddresses(intCount), ByVal CLng(Params(i + 1)), CLng(Params(i + 2)), ByVal 0)
If lngRet = 0 Then GoTo RET
Else
ReDim Preserve pOutData(0 To intOutCount)
pOutData(intOutCount).dwAddress = lpRemoteAddresses(intCount)
pOutData(intOutCount).dwDataSize = CLng(Params(i + 2))
intOutCount = intOutCount + 1
End If
'因为是__stdcall所以最前面的参数应该是在最后面相反最前面的在最后面
dwAddress = lpRemoteAddress + 4 + 5 * (intAgsCount - (i / 3)) + 1
'更改SHELLCODE里的push值,因为开始我们传进来的是我们的进程空间的地址,现在我们要替换成目标进程空间的地址
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, lpRemoteAddresses(intCount), 4, ByVal 0)
If lngRet = 0 Then GoTo RET
intCount = intCount + 1
Else
'如果参数不需要申请内存就直接写入值即可
dwAddress = lpRemoteAddress + 4 + 5 * (intAgsCount - (i / 3)) + 1
dwValue = Params(i + 1)
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, dwValue, 4, ByVal 0)
If lngRet = 0 Then GoTo RET
End If
Next
End If
'计算E8 XXXXXXXX中的XXXXXXXX所在目标进程空间中的地址
dwAddress = lpRemoteAddress + intAgsCount * 5 + 4 + 1
'获取函数的真正地址
CopyMemory dwValue, ByVal CLng(Params(0)), 4
'计算 XXXXXXXX的地址
dwValue = dwValue - (lpRemoteAddress + intAgsCount * 5 + 4) - 5
'更新E8后的XXXXXXXX值这样才能正确执行函数
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, dwValue, 4, ByVal 0)
If lngRet = 0 Then GoTo RET
'创建远程线程执行我们的SHELLCODE,这里我们可以换成Debug的Api比如SetThreadContext和QueueAPC之类的函数也行
hThread = CreateRemoteThread(hProcess, ByVal 0, 0, ByVal lpRemoteAddress + 4, ByVal 0, 0, dwThreadId)
If hThread Then
'等待线程执行结束
WaitForSingleObject hThread, INFINITE
For i = 0 To intOutCount - 1
If pOutData(i).dwDataSize = 4 Then
ReadProcessMemory hProcess, ByVal pOutData(i).dwAddress, pOutData(i).dwDataSize, 4, ByVal 0&
End If
Next
'获取返回值
GetExitCodeThread hThread, lngRet
End If
End If
End If
RET:
'清理我们申请的内存和关闭相关句柄
If hProcess Then
For i = 0 To intCount - 1
If intOutCount = 0 Then
VirtualFreeEx hProcess, ByVal lpRemoteAddresses(i), 0, MEM_RELEASE
Else
For j = 0 To intOutCount - 1
If lpRemoteAddresses(i) = pOutData(j).dwAddress Then
blnIsFind = True
Exit For
End If
Next
If Not blnIsFind Then VirtualFreeEx hProcess, ByVal lpRemoteAddresses(i), 0, MEM_RELEASE
End If
Next
If lpRemoteAddress Then VirtualFreeEx hProcess, ByVal lpRemoteAddress, 0, MEM_RELEASE
End If
If hProcess Then CloseHandle hProcess
If hThread Then CloseHandle hThread
CallAsmFun = lngRet
End Function'获取API函数的地址
Public Function GetFunAddress(ByVal strLibName As String, ByVal strFunName As String) As Long
Dim hMod As Long, dwFunAddress As Long
hMod = LoadLibrary(strLibName)
If hMod Then
dwFunAddress = GetProcAddress(hMod, strFunName)
End If
FreeLibrary hMod
GetFunAddress = dwFunAddress
End Function
解决方案 »
- [求助]如何让鼠标在Form1切换到Form2后,再关闭Form2,就算鼠标位置改变,也不触发Form1的鼠标移动事件?
- 用户控件问题
- vb6.0 中怎么书写一大段的SQL语句
- vb如何实现java中的session在form中传递对象阿。。。。
- VB6.0编译工具坏了
- VB咋读写cookie阿?我这几天问得太多,就剩20分了,我攒10分,就添10分
- 如何判断当前DB已经被Close了?非常简单
- 如何让decimal型字段保留2位小数,并且能够四舍五入?
- 为什么我的KODARK扫出来的bmp在以资源管理器中以WEB方式浏览是全黑的啊!!!!!!!!!!!!!!!
- 退出程序时把分辨率和模式改为用户原来的设置
- VB2005安装打包
- 大家帮我看看我这段代码错在那啊!!!跪求!!
這下可以好好吸取
謝謝,LZ
'参数Params是可变参数其中第一个参数为你写的SHELLCODE Buffer的地址,第二个参数是这个
'SHELLCODE Buffer的长度,第三个参数是API参数个数,从第四个参数起每3个参数形成API函
'数中的一个参数,其中第一个参数表明是否需要申请内存,第二个参数是值(这里如果需要申
'请内存的话这个值将是你需要)写入目标进程的Buffer所在你的进程空间的地址,第三个参数
'是Buffer长度(如果不需要申请内存的这个值可以填0因为默认是以&H68来Push参数的都是4个
'字节对齐,以后的API参数都是一样依次类推下去。直到API参数都完了后就是CALL的机器码E8
'接着是CallValue这个需要计算(我的程序会自动计算),后面紧接着是return 10h,然后再
'填个0好让CPU不要识别错了,因为可能你写到的地方最后一个字节不为0这样return值就会出错
'造成栈不平,参数pOutData为后加上去的主要是用来返回有些API的参数需要返回值的情况下,用
'发很简单传个数组进来即可然后返回的只是一个4个字节数据就保存在它的dwDataSize中,如果
'大于4个字节那么dwAddress是目标进程的数据所在地址dwDataSize是数据的长度,如果我们需要
'把这部分数据读出来只需要再次用ReadProcessMemory读取一次,如果有多个参数就遍历下数组
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function CallAsmFun(ByVal dwProcessId As Long, pOutData() As OUT_DAT, ParamArray Params()) As Long
'lplpRemoteAddress 是在目标进程为ShellCode申请的内存块地址,lpRemoteAddresses()是一些参数申请的内存快地址
'一般只有传结构或者是字符串的时候才需要
Dim lpRemoteAddress As Long, lpRemoteAddresses() As Long, intCount As Integer '在目标进程申请的内存计数
Dim hProcess As Long '进程句柄
Dim lngRet As Long '返回的结果
Dim hThread As Long, dwThreadId As Long '创建的选择线程句柄和TID
Dim i As Integer, j As Integer
Dim dwValue As Long, dwAddress As Long '值和地址
Dim intAgsCount As Integer '参数个数
Dim intOutCount As Integer
Dim blnIsFind As Boolean
'打开目标进程
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwProcessId)
If hProcess Then
'在目标进程申请一块内存,长度是SHELLCODE的长度,好把SHELLCODE写进去
lpRemoteAddress = VirtualAllocEx(hProcess, ByVal 0&, CLng(Params(1)), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
If lpRemoteAddress Then
dwAddress = CLng(Params(0)) '我们进程中SHELLCODE的地址
'把我们生成的SHELLCODE写入目标进程中
If WriteProcessMemory(hProcess, ByVal lpRemoteAddress, ByVal dwAddress, CLng(Params(i + 1)), ByVal 0) Then
'获取需要申请内存的参数计数
For i = Val(Params(2)) * 3 To 3 Step -3
If Val(Params(i)) = 1 Then
intCount = intCount + 1
End If
Next
If intCount > 0 Then
ReDim lpRemoteAddresses(intCount - 1) '申请保存参数申请内存的地址方便后面释放
End If
intCount = 0
intAgsCount = CLng(Params(2)) '我们传进来的第二个参数是API函数的参数个数
For i = intAgsCount * 3 To 3 Step -3 '从最后一个API参数开始取
If Val(Params(i)) = 1 Then
'如果是需要申请内存的参数(比如字符串或者结构等)我们就再申请一块内存
lpRemoteAddresses(intCount) = VirtualAllocEx(hProcess, ByVal 0&, CLng(Params(i + 2)), MEM_COMMIT, PAGE_READWRITE)
'把我们进程空间的才参数内存写入目标进程我们申请的内存块中
If CLng(Params(i + 1)) <> 0 Then
lngRet = WriteProcessMemory(hProcess, ByVal lpRemoteAddresses(intCount), ByVal CLng(Params(i + 1)), CLng(Params(i + 2)), ByVal 0)
If lngRet = 0 Then GoTo RET
Else
ReDim Preserve pOutData(0 To intOutCount)
pOutData(intOutCount).dwAddress = lpRemoteAddresses(intCount)
pOutData(intOutCount).dwDataSize = CLng(Params(i + 2))
intOutCount = intOutCount + 1
End If
'因为是__stdcall所以最前面的参数应该是在最后面相反最前面的在最后面
dwAddress = lpRemoteAddress + 4 + 5 * (intAgsCount - (i / 3)) + 1
'更改SHELLCODE里的push值,因为开始我们传进来的是我们的进程空间的地址,现在我们要替换成目标进程空间的地址
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, lpRemoteAddresses(intCount), 4, ByVal 0)
If lngRet = 0 Then GoTo RET
intCount = intCount + 1
Else
'如果参数不需要申请内存就直接写入值即可
dwAddress = lpRemoteAddress + 4 + 5 * (intAgsCount - (i / 3)) + 1
dwValue = Params(i + 1)
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, dwValue, 4, ByVal 0)
If lngRet = 0 Then GoTo RET
End If
Next
End If
'计算E8 XXXXXXXX中的XXXXXXXX所在目标进程空间中的地址
dwAddress = lpRemoteAddress + intAgsCount * 5 + 4 + 1
'获取函数的真正地址
CopyMemory dwValue, ByVal CLng(Params(0)), 4
'计算 XXXXXXXX的地址
dwValue = dwValue - (lpRemoteAddress + intAgsCount * 5 + 4) - 5
'更新E8后的XXXXXXXX值这样才能正确执行函数
lngRet = WriteProcessMemory(hProcess, ByVal dwAddress, dwValue, 4, ByVal 0)
If lngRet = 0 Then GoTo RET
'创建远程线程执行我们的SHELLCODE,这里我们可以换成Debug的Api比如SetThreadContext和QueueAPC之类的函数也行
hThread = CreateRemoteThread(hProcess, ByVal 0, 0, ByVal lpRemoteAddress + 4, ByVal 0, 0, dwThreadId)
If hThread Then
'等待线程执行结束
WaitForSingleObject hThread, INFINITE
For i = 0 To intOutCount - 1
If pOutData(i).dwDataSize = 4 Then
ReadProcessMemory hProcess, ByVal pOutData(i).dwAddress, pOutData(i).dwDataSize, 4, ByVal 0&
End If
Next
'获取返回值
GetExitCodeThread hThread, lngRet
End If
End If
End If
RET:
'清理我们申请的内存和关闭相关句柄
If hProcess Then
For i = 0 To intCount - 1
If intOutCount = 0 Then
VirtualFreeEx hProcess, ByVal lpRemoteAddresses(i), 0, MEM_RELEASE
Else
For j = 0 To intOutCount - 1
If lpRemoteAddresses(i) = pOutData(j).dwAddress Then
blnIsFind = True
Exit For
End If
Next
If Not blnIsFind Then VirtualFreeEx hProcess, ByVal lpRemoteAddresses(i), 0, MEM_RELEASE
End If
Next
If lpRemoteAddress Then VirtualFreeEx hProcess, ByVal lpRemoteAddress, 0, MEM_RELEASE
End If
If hProcess Then CloseHandle hProcess
If hThread Then CloseHandle hThread
CallAsmFun = lngRet
End Function '获取API函数的地址
Public Function GetFunAddress(ByVal strLibName As String, ByVal strFunName As String) As Long
Dim hMod As Long, dwFunAddress As Long
hMod = LoadLibrary(strLibName)
If hMod Then
dwFunAddress = GetProcAddress(hMod, strFunName)
End If
FreeLibrary hMod
GetFunAddress = dwFunAddress
End Function