前段时间在网上搜远线程代码,全是VC和Delphi的,看了很多帖子都说VB做不了。真的这样吗?
不,仔细研究了网上流传的VC版的dll注入代码后,先用VC做了个,然后翻译成VB的,中间经过不少曲折(我太菜,高手别笑我啊),现将经验写出来,供和我一样的新手参考,如有不对之处还望高手指出。
首先我们要写一个dll供注入,目标程序就选“记事本”好了(notepad.exe)
因为没有装CompileController之类插件的VB环境只能写ActiveX Dll,所以dll就用vc写一个,其实是从网上抄来的啦,嘿嘿,代码如下:
test.cpp: 
#include "stdafx.h"
#include "test.h"
#include <stdlib.h>BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)
{
char szProcessId[64] ;
switch ( reason )
{
case DLL_PROCESS_ATTACH:
{
_itoa ( GetCurrentProcessId(), szProcessId, 10 ); 
MessageBox ( NULL, szProcessId, "RemoteDLL", MB_OK ); 
}
default:
return TRUE; 
}
}
//用向导新建的一个简单dll,添加以上代码,作用是在dll注入以后报出自己的“门牌号”便于验证
然后编译,把test.dll放到C:下面打开vb6新建一个标准exe
添加一个标准模块,添加以下代码:
Option ExplicitPublic Const PROCESS_VM_READ = &H10
Public Const TH32CS_SNAPPROCESS = &H2
Public Const MEM_COMMIT = 4096
Public Const PAGE_READWRITE = 4
 Public Const PROCESS_CREATE_THREAD = (&H2)
 Public Const PROCESS_VM_OPERATION = (&H8)
 Public Const PROCESS_VM_WRITE = (&H20)
 
'Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As String, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
'Public Declare Function GetLastError Lib "kernel32" () As Long
Public Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Public Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As String, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Public Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Public Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Public Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Public Declare Function CreateRemoteThread Lib "kernel32" (ByVal hProcess As Long, ByVal lpThreadAttributes As Long, ByVal dwStackSize As Long, ByVal lpStartAddress As Long, ByVal lpParameter As Long, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function Process32Next Lib "kernel32" (ByVal hSapshot As Long, lppe As PROCESSENTRY32) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As LongPublic Type PROCESSENTRY32
       dwSize  As Long
       cntUseage  As Long
       th32ProcessID  As Long
       th32DefaultHeapID  As Long
       th32ModuleID  As Long
       cntThreads  As Long
       th32ParentProcessID  As Long
       pcPriClassBase  As Long
       swFlags  As Long
       szExeFile  As String * 1024
End Type
双击Form1窗体,把代码改成下面的样子:
Option ExplicitPublic Sub EnumAndInject()Dim MySnapHandle As Long
Dim ProcessInfo As PROCESSENTRY32
Dim MyRemoteProcessId As Long
Dim MyDllFileLength As Long
Dim MyDllFileBuffer As Long
Dim MyReturn As Long
Dim MyStartAddr As Long
Dim MyResult As Long
Dim temp As Long
Dim DllFileName As String MySnapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
ProcessInfo.dwSize = Len(ProcessInfo)
If Process32First(MySnapHandle, ProcessInfo) <> 0 Then
Do
If InStr(ProcessInfo.szExeFile, "notepad.exe") > 0 Then
'遍历进程,查找notepad.exe
MyRemoteProcessId = OpenProcess(PROCESS_CREATE_THREAD + PROCESS_VM_OPERATION + PROCESS_VM_WRITE + PROCESS_VM_READ, False, ProcessInfo.th32ProcessID)
'打开进程获得notepad的句柄供后面的操作使用
DllFileName = "c:\test.dll"
MyDllFileLength = Len(DllFileName)+1
'学过C语言的朋友应该知道字符串最后要一个ASCII 0标志结尾,所以要加1MyDllFileBuffer = VirtualAllocEx(MyRemoteProcessId, 0, MyDllFileLength, MEM_COMMIT, PAGE_READWRITE)
'在指定进程里申请一块内存区域出来供我们存放字符串"c:\test.dll"
'传string给api时,byval byref有区别,应该使用byval,这样会传给api一个标准的C字符指针,不能byref,否则函数调用没问题
'但是起不到预期效果,VirtualAllocEx返回的是申请到的内存地址值.MyReturn = WriteProcessMemory(MyRemoteProcessId, MyDllFileBuffer, DllFileName, MyDllFileLength, temp)
'向刚才申请的内存中写入dll文件路径字符串
'顺便说一下,很多api浏览器上的api声明都是错的,包括VB6自带的也不例外,writeprocessmemory第二个参数要的是
'lpBaseAddress 但是这个值不能传址得到,如果你按byref传址,实际上传的是MyDllFileBuffer变量的地址,而不是它里面存放的那个数字
'上面说了MyDllFileBuffer的数值才是WriteProcessMemory要的地址,所以声明API的时候一定要byval,大家知道空着不写就是默认byref
'下面还有几处不该传址的参数,只要搞清楚API函数要的到底是什么值才可以确定到底传值还是传址,API浏览器仅能供参考,还是要仔细阅读MSDN
MyStartAddr = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA")
'获取loadlibrary函数的地址,这个函数可以载入指定的dll文件,那他的参数呢?就是我们刚才在notepad.exe进程里写入的"c:\test.dll"
'不过还得让CreateRemoteThread告诉他.另外简单的说一下windows下应用程序的内存管理,我也不很懂,呵呵,win32下的应用程序
'的内存区域是隔开的,每个程序有自己的一块内存不能直接访问别的程序的内存区,当然,这里调用的几个系统函数有访问别的程序内存区域的特权
'而且每个应用程序的内存区域都映射到系统内存区域里,也就是说在这里GetProcAddress得到的VB程序里LoadLibraryA函数的入口地址和
'notepad程序里的LoadLibraryA函数地址是一致的(映射的作用),所以不必担心.另外在VB写的程序里
'要使用LoadLibraryA,notepad不是用vc写的吗?要注意根notepad没关系,我们现在是在自己的VB程序里面找LoadLibraryA函数的入口.
'还有要注意函数大小写,api函数和vb不一样的。
MyResult = CreateRemoteThread(MyRemoteProcessId, 0, 0, MyStartAddr, MyDllFileBuffer, 0, temp)
'好了,现在该让LoadLibrary载入"c:\test.dll"吧,现在CreateRemoteThread做的就是在notepad进程中把控制权转到LoadLibraryA的入口
'然后把notepad内存区域中的"c:\test.dll"字符串当作参数传给LoadLibraryA。现在我们的dll文件就在notepad程序中运行了
'dll被注入notepad.exe以后会主动弹出对话框显示出notepad.exe的进程ID,表明注入成功.End IfLoop While Process32Next(MySnapHandle, ProcessInfo) <> 0
End If
CloseHandle MySnapHandleEnd SubPrivate Sub Form_Load()
EnumAndInject
End Sub
以上调用的API详细参数请参考MSDN,没它寸步难行,寒~~

解决方案 »

  1.   

    楼主,好巧,昨天我才来这里提个问题,你就送上门来了哈在网上我看了一些C的,你用的这个方法和我想改造的那个不一样,也许你这种更方便
    但是有弊端.....(具体不说了,你的这种方法不错,可对我要的结果来说,这种方法不会成功)
    因为另外一个程序做了驱动级全局hook WriteProcessMemory等操作内存的API,任何操作内存的API
    都会遭到他的拦截.我研究的那个,我都忘了...因为没研究出来..放弃了一段时间,之后到现在也没弄过
    用loadlib..载入DLL 那个API,用Hook 这个API的方式将指定的DLL载入指定的内存地址不过NicX (NicX)你的研究成果对我有了新的启发...我考虑一下你的思路做法...
    我也采用驱动级编写哈哈...我想这个叫违驱动级合适,我不使用系统API来操作内存
    我用一个C编写的底层硬件操作的东西...嘎嘎...总之谢谢咯...另外多问几句: setwindowshook 这个号称也能实现注入,你看到了吗?但具体方法我没看到
           目前为止我看到了4种方法还有一种是利用内嵌汇编的方法...欢迎指教啊...
      

  2.   

    在setwindowshookex中指定线程id可以实现全局钩子,不过一般来说钩子子程必须是一个dll中导出的函数,如果在2000/xp下还有特殊的底层钩子不受这个限制,比如WH_MOUSE_LL.如果采用前一种方法,系统会自动把含有钩子函数的dll载入到目标线程中。api拦截也可以用windows核心编程里面改exe模块输入节的方法或者用汇编jmpXXX,在网上有现成代码,天极网也有那篇文章
      

  3.   

    老大能给个下载地址吗,我看看啊....我说的用全局钩子实现DLL注入,原理是这样,钩子的最基本形式是线程内钩子
    扩展到全局,就要用dll 为什么必须是DLL 而且是标准的DLL ,是因为全局钩子安装后
    系统会将这个DLL 注入到每个进程中,这样才实现了全局hook,既然是将dll注入到了所有进程
    那么也就是说,只要适当的添加代码,就可以在出现钩子消息时进行某些事情...)_|_(
      ^
      ~
    这个某些事情不用多说了吧....当然是想注入后执行的代码..........你说的改输入节...不知道改谁的输入节,估计你说的是实现全局拦截API的那个
    这种方法行不通,因为这个程序启动的时候会自动扫描程序数据..汇编jum...这个就不明白了,那个程序在调用系统API时进行了jum,你在jum那到底
    什么时候jum合适呢?盼复啊...主要是你说的:。api拦截也可以用windows核心编程里面改exe模块输入节的方法或者用汇编jmpXXX,在网上有现成代码,天极网也有那篇文章
    这篇文章的地址啊....
      

  4.   

    http://www.yesky.com/98/1952598.shtml   Windows 2000下Api函数的拦截分析
    http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c5767    Three Ways To Inject Your Code Into Another Process
    http://www.vb-helper.com/howto_make_standard_dll.html   how to make a standard DLL in Visual Basic 6
      

  5.   

    第一个 ... 根本没什么技术可言...第二个 ... e文太多...太费神 ....第三个 ... 怎么制作标准的DLL ... 还值得一看,但不知道这种方法和中文网上流传的那种方法
                                      区别到底是什么? 他用的好像是def开关??
      

  6.   

    这种方法和国内网站的不一样是种一劳永逸的方法,原理是用vb写一个link.exe介入vb IDE和真正的link。exe之间,添加export参数,用的时候只要和vc一样写一个def文件就可以编写能导出符号的dll了
      

  7.   

    这很简单很容易
    但是要远程注入VB写的DLL也就是使用插件的写成的DLL就很难实现了
      

  8.   

    嗯,VB写的Dll可以正常插入到目标进程,msvbvm60.dll也会被一起插入目标进程,但是vb的dll缺省的入口是__vbaS,Link的时候参数是/ENTRY:__vbaS而不会是DllMain或者Main,在存在res文件的情况下,是有可能定义入口函数的。
      

  9.   

    楼上的兄弟用VB写的DLL插入到目标进程中起着用了吗??
      

  10.   

    dll载入后vb又不调用里面的函数,当然不起作用了,我一般都注VC写的dll的。
      

  11.   

    http://www.baidu.com/baidu?word=%CA%D4%B9%FD%D3%C3%BD%F0%C9%BD%D3%CE%CF%C0%D0%DE%B8%C4%BA%EC%BE%AF%B6%FE%B5%C4%BD%F0%C7%AE&tn=myie2dg
      

  12.   

    VB写的改装DLL是可以插入远程进程的,而且也可以调用里面的函数(用CreateRemoteThread),只是如上朋友所说,需要插入一个Msvbvm60.dll不过多个函数的传入,还是一个问题.是否非得把参数也一起放到宿主进程里,再把起始地址作为参数传给远程线程?有没有直接的办法??我现在已经可以成功地插入VC的DLL以及VB的DLL到目标进程了,并且里面的函数也都调用成功了.只是,那些函数都是无参函数,有参数的不知道如何调用,每次都是非法操作.另外,好象可以把VB工程里标准模块内的公共函数写到宿主进程里,再进行远程调用....?我还没有来得及试,不过把函数写到宿主进程里倒是可以,晚上试下.....记事本又要痛苦了
      

  13.   

    VB写的DLL也能成功??
    我倒是试过N次没一次成功只是成功插入了但是根本不执行代码
    这样有什么用啊
      

  14.   

    现在还有人在讨论这个问题啊,呵呵。
    TO:majian
    带参的函数是可以的,在目标的内存里面分配空间,然后把参数写进去,先CreateRemoteThread调用目标进程的函数就行了,不过只能一个参数。想要多个参数可以用一个结构体把参数封装起来,传递及构体指针就好了。
    另外,与注入的DLL间的通信不一定非要这样不可,Windows下进程间通信的资料还是很多的。
      

  15.   

    NicX(透矢) ( ) 信誉:100    Blog  2006-09-30 01:19:00  得分: 0  
     
     
       现在还有人在讨论这个问题啊,呵呵。
    TO:majian
    带参的函数是可以的,在目标的内存里面分配空间,然后把参数写进去,先CreateRemoteThread调用目标进程的函数就行了,不过只能一个参数。想要多个参数可以用一个结构体把参数封装起来,传递及构体指针就好了。
    另外,与注入的DLL间的通信不一定非要这样不可,Windows下进程间通信的资料还是很多的。
      
     //呵呵,我现在就是使用这种方法传多参数的.因为之前下载了一个C的代码,它就是这么做的,于是在VB里也效仿之,嘿~~PS:这个问题当然还有人讨论啊.毕竟这与"用筷子挑汤"差不多了......^_^