利用VB编写dll注入其他进程

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

利用VB编写dll注入其他进程的源代码12008-06-12 07:37此帖主要讲一下dll的注入与卸载(叫反注入貌似不太恰当,反正就是那个意思),以及如何编写一个注入用dll。因为在网上好多讲注入的帖子中的dll都讲得很简单,简单的show一个msgbox。问题是注入之后,dllmain执行一次就返回了,接着要怎么继续让dll做事情很多菜鸟(包括我)都不知道。所以就研究了下,贴在这里。

第一部分讲的是注入程序:

dll注入的核心就是用CreateRemoteThread函数在目标进程中创建一个线程(如果你不知道线程是什么?just google it),该线程只有一个作用,就是LoadLibraryA我们的dll,而LoadLibraryA又会调用dll的DllMain函数并发送DLL_PROCESS_ATTACH参数告诉dll你被加载了。此时我们的dll就成为了目标进程的一部分,于是乎,你该干吗就可以干吗去了。

ok,来说说代码吧。下面是api申明,放在模块当中。
程序代码
Option Explicit
'dll注入程序
'api申明模块
'
'蓝色炫影 制作
'
'
'最后更新 2008/05/06
'您可以自由用于非商业用途。
'请保留此行版权信息,谢谢。

Public Const PROCESS_VM_READ = &H10
Public Const TH32CS_SNAPPROCESS = &H2
Public Const MEM_COMMIT = 4096
Public Const MEM_DECOMMIT = &H4000
Public Const PAGE_READWRITE = 4
Public Const PROCESS_Create_THREAD = (&H2)
Public Const PROCESS_VM_OPERATION = (&H8)
Public Const PROCESS_VM_WRITE = (&H20)
Public Const PROCESS_ALL_ACCESS = &H1F0FFF
Public Const INFINITE = &HFFFF ' Infinite timeout

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 VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, _
ByVal lpAddress As Long, ByVal dwSize As Long, _
ByVal dwFreeType As Long) As Long
'这两个api的作用是在目标进程中分配一段空白内存供程序使用。在vb的api浏览器中是找不到的。

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
'得到函数地址与dll模块地址

Public Declare Function CreateToolhelp32Snapshot Lib "kernel32" _
(ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Public Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, _
lppe As PROCESSENTRY32) As Long
Public Declare Function Process32Next Lib "kernel32" (ByVal hSapshot As Long, _
lppe As PROCESSENTRY32) As Long
'这三个api用来遍历进程

Public Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDe

siredAccess As Long, ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'打开与关闭进程句柄

Public Declare Function WriteProcessMemory Lib "kernel32" _
(ByVal hProcess As Long, ByVal lpBaseAddress As Long, lpBuffer As Any, _
ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
'这里注意lpBaseAddress的传送方式是byval,和api浏览器中的声明是不一样的。 _
byval是传值,默认是byref是传址,也就是传递的是参数在内存中的地址
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
'这里也是一样,几个参数的传递方式与api浏览器中的声明不一样
Public Declare Function WaitForSingleObject Lib "kernel32" _
(ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function GetExitCodeThread Lib "kernel32" _
(ByVal hThread As Long, lpExitCode 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

接着在窗体中画一个Text1用来输入准备注入的dll名,外加2个Button,Command1是注入,Command2是卸载。
窗体代码:

程序代码
Option Explicit
'dll注入程序
'主窗体代码
'
'蓝色炫影 制作
'
'
'最后更新 2008/05/06
'您可以自由用于非商业用途。
'请保留此行版权信息,谢谢。

Public Sub Inject()
'注入子程序

Dim MySnapHandle As Long '存放进程快照句柄
Dim ProcessInfo As PROCESSENTRY32
Dim MyRemoteProcessId As Long '目标进程pid
Dim MyDllFileName As String 'dll文件路径
Dim MyDllFileLength As Long 'dll文件名长度
Dim MyDllFileBuffer As Long '写入dll文件名的内存地址
Dim MyAddr As Long '执行远程线程代码的起始地址。这里等于LoadLibraryA的地址
Dim MyReturn As Long

MySnapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
ProcessInfo.dwSize = Len(ProcessInfo)
'建立进程快照

If Process32First(MySnapHandle, ProcessInfo) <> 0 Then
'开始遍历进程
Do
If InStr(ProcessInfo.szExeFile, "explorer.exe") > 0 Then
'遍历进程,查

找explorer.exe

MyDllFileName = App.Path & "\" & IIf(LCase(Right(Text1, 4)) = ".dll", Text1, Text1.Text & ".dll")
'dll文件路径
MyDllFileLength = LenB(StrConv(MyDllFileName, vbFromUnicode)) + 1
'这里把dll文件名从Unicode转换成Ansi,否则英文字母是2个字节。 _
顺便说一下,学过C的应该知道字符串要以/0标志结尾,所以dll文件名长度要加上1个字节存放Chr(0)

MyRemoteProcessId = OpenProcess(PROCESS_ALL_ACCESS, False, ProcessInfo.th32ProcessID)
'得到进程的句柄
If MyRemoteProcessId = 0 Then MsgBox "OpenProcess Error"


MyDllFileBuffer = VirtualAllocEx(MyRemoteProcessId, 0, MyDllFileLength, MEM_COMMIT, PAGE_READWRITE)
'在目标进程中申请分配一块空白内存区域。内存的起始地址保存在MyDllFileBuffer中。 _
这块内存区域我们用来存放dll文件路径,并作为参数传递给LoadLibraryA。
If MyDllFileBuffer = 0 Then MsgBox "VirtualAllocEx Error"

MyReturn = WriteProcessMemory(MyRemoteProcessId, MyDllFileBuffer, ByVal (MyDllFileName), MyDllFileLength, 0)
'在分配出来的内存区域中写入dll路径径。注意第二个参数传递的是MyDllFileBuffer的内容, _
而不是MyDllFileBuffer的内存地址。
If MyReturn = 0 Then MsgBox "WriteProcessMemory Error"

MyAddr = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA")
'得到LoadLibraryA函数的起始地址。他的参数就是我们刚才写入的dll路径。但是LoadLibraryA本身是不知道参数在哪里的。 _
接下来我们就用CreateRemoteThread函数告诉他参数放在哪里了。
If MyAddr = 0 Then MsgBox "GetProcAddress Error"

MyResult = CreateRemoteThread(MyRemoteProcessId, 0, 0, MyAddr, MyDllFileBuffer, 0, 0)
'好了,现在用CreateRemoteThread在目标进程创建一个线程,线程起始地址指向LoadLibraryA, _
参数就是MyDllFileBuffer中保存的dll路径。
If MyResult = 0 Then MsgBox "error CreateRemoteThread"
'接下来你可以使用WaitForSingleObject等待线程执行完毕。 _
并用GetExitCodeThread得到线程的退出代码,用来判断时候正确执行了dll中的代码。
CloseHandle MyResult
CloseHandle MyRemoteProcessId
'扫地工作
End If
Loop While Process32Next(MySnapHandle, ProcessInfo) <> 0
End If

CloseHandle MySnapHandle
End Sub

Private Sub Command1_Click() '点击注入按钮
Inject '执行注入
End Sub
接下来我们讲怎么把注入进去的dll卸载掉,其实与注入基本上是一样的,只不过用到的API要换一下。
我们先在目标进程当中执行GetModuleHandleA,得到我们dll的句柄,然后再远程执行FreeLibrary,把我们的dll卸载。
那么这里

有个问题,如何得到GetModuleHandleA的返回值呢?
那就要用到WaitForSingleObject,这个函数的作用是等待远程线程执行完毕,之后我们只要调用GetExitCodeThread得到远程线程的退出码就行了。因为远程线程是调用GetModuleHandleA,所以退出码就是GetModuleHandleA的返回值。

代码如下:

程序代码
Private Sub Enject()

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 MyAddr As Long
Dim MyResult As Long
Dim MyDllFileName As String
Dim dwHandle As Long

MySnapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
ProcessInfo.dwSize = Len(ProcessInfo)


If Process32First(MySnapHandle, ProcessInfo) <> 0 Then
Do
If InStr(ProcessInfo.szExeFile, "explorer.exe") > 0 Then
MyRemoteProcessId = OpenProcess(PROCESS_ALL_ACCESS, False, ProcessInfo.th32ProcessID)
If MyRemoteProcessId = 0 Then MsgBox "error OpenProcess"

MyStartAddr = GetProcAddress(GetModuleHandle("Kernel32"), "GetModuleHandleA")
'与注入一样,只不过这里换成了GetModuleHandleA. _
原理就是先在目标进程执行GetModuleHandleA得到我们的dll的地址,然后再用FreeLibrary卸载掉我们的dll。
If MyStartAddr = 0 Then MsgBox "error GetProcAddress"

MyDllFileName = IIf(LCase(Right(Text1, 4)) = ".dll", Text1, Text1.Text & ".dll")
MyDllFileLength = LenB(StrConv(MyDllFileName, vbFromUnicode)) + 1

MyDllFileBuffer = VirtualAllocEx(MyRemoteProcessId, 0, MyDllFileLength, MEM_COMMIT, PAGE_READWRITE)
If MyDllFileBuffer = 0 Then MsgBox "error VirtualAllocEx"

MyReturn = WriteProcessMemory(MyRemoteProcessId, MyDllFileBuffer, ByVal (MyDllFileName), MyDllFileLength, temp)
If MyReturn = 0 Then MsgBox "error WriteProcessMemory"

MyResult = CreateRemoteThread(MyRemoteProcessId, 0, 0, MyAddr, MyDllFileBuffer, 0, temp)
'都与注入一样。执行到这里就得到了
WaitForSingleObject MyResult, INFINITE '等待远程线程执行完毕。
GetExitCodeThread MyResult, dwHandle '这里可以得到远程线程的返回值,也就是GetModuleHandleA返回的我们的dll的句柄。

VirtualFreeEx MyRemoteProcessId, MyDllFileBuffer, MyDllFileLength, MEM_DECOMMIT
'释放掉我们申请的内存段
CloseHandle MyResult

MyAddr = GetProcAddress(GetModuleHandle("Kernel32"), "FreeLibrary")
If MyAddr = 0 Then MsgBox "error FreeLibrary"
MyResult = CreateRemoteThread(MyRemoteProcessId, 0, 0, MyAddr, dwHandle, 0, temp)
'这次不需要再用WriteProcessMemory写入FreeLibrary的参数了, _
因为我们的dll的句柄刚才已经保存在dwHandle里面了。
If MyResult = 0 Then MsgB

ox "error CreateRemoteThread"
CloseHandle MyResult
CloseHandle MyRemoteProcessId
End If
Loop While Process32Next(MySnapHandle, ProcessInfo) <> 0
End If


CloseHandle MySnapHandle

End Sub
我们再加上几个按钮的动作,整个注入程序就完成了
程序代码
Private Sub Command1_Click()
Inject
End Sub

Private Sub Command2_Click()
Enject
End Sub

Private Sub Form_Load()
Text1 = GetSetting(App.Title, "dllname", "dllname")
End Sub

Private Sub Form_Unload(Cancel As Integer)
SaveSetting App.Title, "dllname", "dllname", Text1
End Sub

Private Sub Text1_GotFocus()
Text1.SelStart = 0
Text1.SelLength = Len(Text1.Text)
End Sub

在text1里面输入想要注入的dll文件名,然后点Command1就行了。


相关文档
最新文档