- 主题
- 0
- 积分
- 854
- 贝壳
- 854 个
- 性别
- 男
- 来自
- 贵州遵义
- 注册时间
- 2005-3-26
- 最后登录
- 2011-2-26
|
前段时间在网上搜远线程代码,全是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
- 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 Explicit
- Public 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 Long
- Public 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 Explicit
- Public 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标志结尾,所以要加1
- MyDllFileBuffer = 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 If
- Loop While Process32Next(MySnapHandle, ProcessInfo) <> 0
- End If
- CloseHandle MySnapHandle
- End Sub
- Private Sub Form_Load()
- EnumAndInject
- End Sub
复制代码
以上调用的API详细参数请参考MSDN,没它寸步难行,寒~~ |
|