dll进样器32位和x64 dll文件不能在notepad.exe x64中工作

时间:2016-03-03 01:00:45

标签: vb6 64-bit dll-injection

我有一个用Visual Basic 6编译的DLL注入器,我试图在x64 notepad.exe上注入我的DLL(x64),但没有任何作用。

我在网上搜索过这个并看到了这个:

  

[重要:32位/ 64位]

     

这是一个可移植性表:

     
      
  • 32位程序在32位目标中注入32位dll
  •   
  • 32位程序在64位目标中注入64位dll
  •   
  • 64位程序在32位目标中注入32位dll
  •   
  • 64位程序在64位目标中注入64位dll
  •   

如果这是真的,那么我的注射器应该正常工作。

有人能帮助我吗?

使用的代码:

Module1.bas

Option Explicit

Private Const INFINITE                  As Long = &HFFFF

Private Const TOKEN_ADJUST_PRIVILEGES   As Long = &H20
Private Const TOKEN_QUERY               As Long = &H8
Private Const SE_PRIVILEGE_ENABLED      As Long = &H2
Private Const ANYSIZE_ARRAY             As Long = 1

Private Const SE_DEBUG_NAME             As String = "SeDebugPrivilege"

Private Const PAGE_READWRITE            As Long = &H4
Private Const MEM_RELEASE               As Long = &H8000
Private Const MEM_COMMIT                As Long = &H1000

Private Const STANDARD_RIGHTS_REQUIRED  As Long = &HF0000
Private Const SYNCHRONIZE               As Long = &H100000
Private Const PROCESS_VM_OPERATION As Long = (&H8)
Private Const PROCESS_VM_WRITE As Long = (&H20)

Private Const TH32CS_SNAPPROCESS As Long = 2&


Private Const PROCESS_ALL_ACCESS        As Long = _
                                        (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION Or &HFFF)

Private Type PROCESSENTRY32
    dwSize As Long
    cntUsage As Long
    th32ProcessID As Long
    th32DefaultHeapID As Long
    th32ModuleID As Long
    cntThreads As Long
    th32ParentProcessID As Long
    pcPriClassBase As Long
    dwFlags As Long
    szexeFile As String * 260
End Type

Private Type Luid
    lowpart                     As Long
    highpart                    As Long
End Type

Private Type LUID_AND_ATTRIBUTES
    pLuid                       As Luid
    Attributes                  As Long
End Type

Private Type TOKEN_PRIVILEGES
    PrivilegeCount              As Long
    Privileges(ANYSIZE_ARRAY)   As LUID_AND_ATTRIBUTES
End Type

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private 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
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function CreateRemoteThread Lib "kernel32" (ByVal hProcess As Long, lpThreadAttributes As Long, ByVal dwStackSize As Long, lpStartAddress As Long, lpParameter As Any, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32.dll" (ByVal hProcess As Long, ByRef lpAddress As Any, ByRef dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As Luid) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As Any, ReturnLength As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32.dll" (ByVal lFlags As Long, lProcessID As Long) As Long
Private Declare Function ProcessFirst Lib "kernel32.dll" Alias "Process32First" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function ProcessNext Lib "kernel32.dll" Alias "Process32Next" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long


Public Function InjectByPID(ByVal sDllPath As String, ByVal lProcessID As Long) As Boolean
    Dim lProc As Long
    Dim lLibAdd As Long
    Dim lMem As Long
    Dim lRet As Long
    Dim lThread As Long

    On Local Error GoTo InjectByPID_Error

    '//Adjust token privileges to open system processes
    Call AdjustPrivileges(GetCurrentProcess)

    '// Open the process with all access
    lProc = OpenProcess(PROCESS_ALL_ACCESS, False, lProcessID)
    If lProc = 0 Then GoTo InjectByPID_Error

    '// Get the address of LoadLibrary
    lLibAdd = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA")
    If lLibAdd = 0 Then GoTo InjectByPID_Error

    '// Allocate memory to hold the path to the Dll File in the process's memory
    lMem = VirtualAllocEx(lProc, 0, Len(sDllPath), MEM_COMMIT, PAGE_READWRITE)
    If lMem = 0 Then GoTo InjectByPID_Error

    '// Write the path to the Dll File in the location just created
    Call WriteProcessMemory(lProc, ByVal lMem, ByVal sDllPath, Len(sDllPath), lRet)
    If lRet = 0 Then GoTo InjectByPID_Error

    '// Create a remote thread that starts begins at the LoadLibrary function and _
     is passed are memory pointer
    lThread = CreateRemoteThread(lProc, ByVal 0, 0, ByVal lLibAdd, ByVal lMem, 0, 0&)
    If lThread = 0 Then GoTo InjectByPID_Error

    '// Wait for the thread to finish
    Call WaitForSingleObject(lThread, INFINITE)

    '// Free the memory created on the other process
    Call VirtualFreeEx(lProc, lMem, Len(sDllPath), MEM_RELEASE)

    '//Release the handle to the other process
    Call CloseHandle(lProc)

    InjectByPID = True

    On Error GoTo 0
    Exit Function

InjectByPID_Error:
    '// Free the memory created on the other process
    Call VirtualFreeEx(lProc, lMem, Len(sDllPath), MEM_RELEASE)
    '//Release the handle to the other process
    Call CloseHandle(lProc)
End Function

Public Function AdjustPrivileges(ByVal lProcessID As Long) As Boolean
    Dim lToken              As Long
    Dim tTOKEN_PRIVILEGES   As TOKEN_PRIVILEGES

    On Local Error GoTo AdjustPrivileges_Error

    If Not OpenProcessToken(lProcessID, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, lToken) = 0 Then
        With tTOKEN_PRIVILEGES
            If LookupPrivilegeValue(vbNullString, SE_DEBUG_NAME, .Privileges(0).pLuid) = 0 Then
                Exit Function
            End If
            .PrivilegeCount = 1
            .Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
        End With
        If Not AdjustTokenPrivileges(lToken, 0, tTOKEN_PRIVILEGES, Len(tTOKEN_PRIVILEGES), 0&, 0&) = 0 Then
            AdjustPrivileges = True
        End If
    End If

    On Error GoTo 0
    Exit Function

AdjustPrivileges_Error:

End Function

'Get PID
Public Function whereISmyFUFUprocess(ByVal ProcessName As String) As Long
    Dim procSnapshot As Long
    Dim uProcess As PROCESSENTRY32
    Dim success As Long
    Dim ProcessId As Long
    Dim ProcessId_found As Boolean

    ProcessId_found = False

    procSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0&)

    If procSnapshot = -1 Then Exit Function

    uProcess.dwSize = Len(uProcess)
    success = ProcessFirst(procSnapshot, uProcess)

    If success = 1 Then
        Do
            If LCase(VBA.Left$(uProcess.szexeFile, InStr(1, uProcess.szexeFile, Chr(0)) - 1)) = LCase(ProcessName) Then
                ProcessId = uProcess.th32ProcessID
                Debug.Print "First process found with PID: " & ProcessId
                    If ProcessId_found = True Then
                        Debug.Print "Second process found with PID: " & ProcessId
                        whereISmyFUFUprocess = ProcessId
                        Exit Do
                    End If
                  ProcessId_found = True
            End If
        Loop While ProcessNext(procSnapshot, uProcess)

    End If

    If whereISmyFUFUprocess = 0 Then
        whereISmyFUFUprocess = ProcessId
    End If

    Call CloseHandle(procSnapshot)

End Function

表单1

Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)


Private Sub Command1_Click()

Dim PID As Long


' // Run Notepad
    Shell "notepad.exe", vbNormalFocus

    Sleep 1000

   PID = whereISmyFUFUprocess("notepad.exe")

   Sleep 1000

   InjectByPID "Project1.dll", PID

End Sub

2 个答案:

答案 0 :(得分:0)

检查您是否正在获取进程ID。

如果我没记错的话(我之前已经尝试过这种方法),你就无法从只使用API​​的32位进程中获取64位进程列表。所以你的VB6应用程序只能看到32位进程。您需要(另一个)64位帮助程序来为您提供64位和32位进程ID的列表,然后您就可以使用它们了。

编辑#1: CreateToolhelp32Snapshot()的文档提及:

  

如果指定的进程是64位进程且调用者是a   32位进程,此函数失败,最后一个错误代码是   ERROR_PARTIAL_COPY(299)。

更正:无关紧要,因为您在没有指定进程的情况下调用CreateToolhelp32Snapshot()以包含在快照中(即第二个参数为null)

通过获取64位记事本过程的PID并手动输入,您仍然可以在调试时检查程序的注入部分是否正常工作。直接到InjectByPID()。

编辑#2:您可能会通过WMI获得包含64位进程的进程列表。请参阅this Super User question

CORRECTION: CreateToolhelp32Snapshot()列出了64位和32位进程。我可能与EnumProcesses()混淆了。

答案 1 :(得分:0)

行。这可能不是一个完整/直接的答案,因为它只提供解决问题的方向;另外,我不熟悉amd64汇编代码,所以我无法帮助你。

根据this articleCreateRemoteThread()处理64位进程需要从另一个64位进程调用注意:这个答案是基于那个我没有测试过的假设。

知道这一点,你有三(3)个选择:

  1. 使用x64代理代表x86 / VB6注入器调用CreateRemoteThread()。其他一切都是在VB6中完成的,包括注入引导代码。

    • 要求:使用您选择的语言和工具(代理)构建的x64可执行文件由代理调用的一些手写的amd64机器代码(引导代码)。
    • 难度:具有挑战性(除非编写和调试手写的amd64汇编代码是您最喜欢的消遣之一)
    • 优点:相对来说,没有。
    • 缺点:两部分注入器 plus 您需要编写一些amd64机器代码来注入您的DLL。不必要的复杂。
    • 伪代码/程序流程 (1) x86注入器获取进程ID,然后处理到目标(x64)进程; (2) x86注入器将一块内存分配到目标(x64)进程,该进程大到足以保存注入的DLL的路径以及负责的amd64引导代码用于将该DLL加载到远程进程中; (3) x86注入器向已分配的内存写入DLL路径和引导代码; (4) x86注入器执行x64代理并将复制的进程句柄和指向已分配内存的指针传递给它(如果它没有开始,则偏移到引导代码的入口点)分配的内存块的开头); (5) x64代理调用CreateRemoteThread(),包含引导代码的进程句柄和入口点地址; (6)引导代码获取" kernel32.dll",proc的模块地址。地址LoadLibraryW()并从提供的路径加载DLL;远程线程从那里继续; (7)同时,x64代理返回CreateRemoteThread()调用的x86注入结果。
  2. 好吧,如果我们为注入添加x64代理的依赖关系,为什么不让它执行整个DLL加载而不是一些引导代码。然后,x64代理负责(至少)解析LoadLibraryW()的地址,并调用LoadLibraryW()将DLL加载到目标进程中。

    最简单的路径是让x86注入器找到目标的进程ID,当目标进程是64位时,传递该进程ID&注入的DLL到x64代理的路径,所以它会进行注入。

    • 要求:使用您选择的语言和工具(代理)构建的x64可执行文件。
    • 难度容易;只需要了解为x64平台构建的另一种语言
    • 优点:没有更多的amd64机器代码可以搞乱。
    • 缺点:仍然是一个由两部分组成的注射器。
    • 伪代码/程序流程 (1) x86注入器获取目标(x64)进程的ID; (2) x86注入器执行x64代理并将目标进程ID和要注入的DLL的路径传递给它; (3) x64代理在目标进程中分配内存,将DLL路径写入其中,然后解析&通过CreateRemoteThread()调用CreateRemoteThread()以及指向我们注入远程进程的DLL路径的地址;远程线程从那里继续; GetModuleHandle()调用之后(4)(或者如果某些内容失败之前),x64代理会将调用结果或遇到的任何错误返回给x86注入器。
  3. 利用天堂之门(概念here;使用here的例子)从x86,VB6构建的注入器中运行amd64代码。

    • 要求:一些(机器编译的)amd64代码,可以调用LoadLibraryW()CreateRemoteThread()LdrLoadDll() easy part ...);
      ...和我们需要在我们的进程中分配的大量x86代码空间来放置amd64机器代码字节,修复堆栈加载64 -bit二进制文件,使用RtlEqualUnicodeString() ntdll.dll [[]通过挂钩和修补{{1}}的ntdll.dll来加载kernel32.dll的amd64版本,这样我们就可以加载了" KERNEL32.DLL"第二次但是在另一个地址,*或*通过释放加载的32位kernel32.dll并在我们运行amd64代码]的情况下将其替换为64位 ,切换到64位模式,然后清理并撤消所有内容以安全返回到x86模式。
    • 难度:很难。不确定所有可以在VB6中完成(具体来说,与堆栈相关的部分)。
    • 优点:单件式喷油器。
    • 缺点:如果实施得很好,没有。
    • 伪代码/程序流程:您应该阅读http://rce.co/knockin-on-heavens-gate-dynamic-processor-mode-switching/上的文章并查看完全为了做什么而编写的代码( HeavenInjector )您正在尝试这样做,即将库从32位进程注入64位进程。此技术的另一个实施示例是WOW64Ext Library
  4. 希望在阅读完之后你应该知道下一步该尝试什么。