2016-03-03 7 views
1

У меня есть инжектор DLL, скомпилированный с Visual Basic 6, и я пытаюсь внедрить свою DLL (x64) в x64 notepad.exe, но ничего работает.dll инжектор 32 бит и x64 dll файл не работают в notepad.exe x64

Я искал в Интернете об этом, и увидел это:

[ВАЖНО: 32-BIT/64-BIT]

Это портативность стол:

  • 32bit программа вводят 32-битную DLL в 32-разрядную цель
  • 32-разрядная программа вводит 64-разрядную DLL в 64-разрядную цель
  • 64-разрядная программа injec т 32bit длл в целевой 32-битный
  • 64-битной программы Inject DLL 64-битной в 64-битной цели

Если это верно, так что мой инжектор должен работает.

Может кто-нибудь помочь мне, пожалуйста?

код используется:

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 
+0

VB6 НЕ МОЖЕТ создавать 64-битную dll/exe. – nabuchodonossor

+0

@nabuchodonossor, Затем для ввода 64-разрядной DLL в любой 64-битный исполняемый файл, окончательный исполняемый файл, сгенерированный компилятором VB6, должен быть также 64-битным exe? У меня 64-разрядная dll, сделанная в Delphi XE5, и инжектор VB6 32bit (код выше). Основываясь на приведенной выше цитате, скажем, что 32-разрядный инжектор exe может вводить 64-битную DLL в 64-битную цель. Поэтому я этого не понимал, потому что не работал. –

+0

Вы запустили его в 32-битной среде? Что я имею в виду: он работал с 32-разрядной dll и 32-разрядным приложением? – nabuchodonossor

ответ

0

OK. Это может быть не полный/прямой ответ, поскольку он предлагает только те направления, которые вы могли бы предпринять, чтобы решить вашу проблему; Кроме того, я не разбираюсь в ассемблере amd64, поэтому я не могу вам помочь.

Согласно this article, для CreateRemoteThread() работать на 64-битных процессов он должен быть вызван из другого 64-разрядного процесса (Примечание: этот ответ основан на том предположении, что я не проверял) ,

Зная, что у вас есть три (3) варианты:

  1. Используйте x64 прокси для вызова CreateRemoteThread() от имени вашего x86/VB6 инжектора. Все остальное сделано в VB6, включая инъекцию кода начальной загрузки.

    • Требования: x64 исполняемый файл, построенный с помощью языка и инструментов выбора (прокси) и некоторые рукописные, amd64 машинный код, чтобы называться по доверенности (код самонастройки).
    • Сложность: Оспаривание (если писать & отладки рукописного код amd64 сборки не входит в числе ваших любимых игр)
    • Преимущества: условно говоря, ни один.
    • Недостатки: Двухкомпонентный инжектор plus вам нужно написать некоторый машинный код amd64, чтобы ввести вашу DLL. Ненужный комплекс.
    • поток Псевдокод/​​Программа: (1) x 86 инжектора приобретает идентификатор процесса, а затем обработать целевой процесс (x64); (2) x86 инжектор выделяет блок памяти в целевой (x64) процесс, достаточно большой, чтобы удерживать путь к DLL, в которую вводится , а также код начальной загрузки amd64, ответственный за загрузку этой DLL в удаленный процесс; (3) x86 инжектор записывает в выделенную память путь к DLL и код начальной загрузки; (4) x86 инжектор выполняет прокси-сервер x64 и передает ему дублированный дескриптор процесса и указатель на выделенную память (смещение в точку входа кода начальной загрузки, если оно не начинается в начале выделенного блока памяти); (5) x64 прокси-вызовы CreateRemoteThread() с дескриптором процесса и адресом точки входа кода начальной загрузки; (6) Загрузочный код получает адрес модуля «kernel32.dll», proc.адрес LoadLibraryW() и загружает DLL из предоставленного пути; удаленный поток продолжается оттуда; (7) в то же время, прокси-сервер x64 возвращается к результату инжектора x86 вызова CreateRemoteThread().
  2. Ну, если мы добавим зависимость от 64 прокси-сервер для нашего инъекции, почему не иметь это сделать все DLL загрузки вещь вместо некоторого самонастройки кода. Прокси-сервер x64 - это также, ответственный (по крайней мере) за разрешение адреса и вызов LoadLibraryW() для загрузки нашей DLL в целевой процесс.

    Простейший путь состоит в том, чтобы инжектор x86 нашел идентификатор процесса цели, а когда целевой процесс является 64-разрядным, передайте этот идентификатор процесса & путь к вложенной DLL к прокси-серверу x64, чтобы он выполнял инъекцию вместо.

    • Требования: x64 исполняемый файл, построенный с помощью языка и инструментов выбора (прокси).
    • Сложность: Простая; просто нужно знание другого языка, который строится на платформе x64.
    • Преимущества: Нет больше машинного кода amd64, с которым можно связаться.
    • Недостатки: Еще двухкомпонентный инжектор.
    • Псевдокод/​​поток программы: (1) x 86 инжектора приобретает идентификатор целевого процесса (64); (2) x86 инжектор выполняет прокси-сервер x64 и передает ему идентификатор целевого процесса и путь к DLL для ввода; (3) Прокси-сервер x64 выделяет память в целевом процессе, записывает в нее путь к DLL, а затем разрешает & вызовы LoadLibraryW() через CreateRemoteThread() вместе с адресом, указывающим на путь DLL, который мы вводим в удаленный процесс; удаленный поток продолжается оттуда; (4) после вызова CreateRemoteThread() (или раньше, если что-то не получается), прокси-сервер x64 возвращает инжектору x86 результат вызова или любую возникшую с ним ошибку.
  3. Воспользоваться Врата Небес (концепция here, пример использования here) для запуска кода amd64 из вашего x86, VB6 встроенным инжектором.

    • Требования: некоторые (машинно-скомпилирован) amd64 код, который будет вызывать GetModuleHandle(), LoadLibraryW() и CreateRemoteThread() (что легко часть ...);

      ... и весь код x86, который нам нужно выделить в нашем процессе, место для ввода байтов машинного кода amd64, исправить стек для загрузки 64-разрядных двоичных файлов, загрузить сборку amd64 kernel32.dll, используя LdrLoadDll() из ntdll.dll [[] путем перехвата и исправления RtlEqualUnicodeString() файла ntdll.dll, поэтому мы можем загрузить «kernel32.dll» второй раз, но с другим адресом * или *, освободив загруженное 32-битное ядро32. dll и заменив его на 64-битный, когда мы запускаем код amd64 ]], переходим в 64-разрядный режим, а затем очищаем и отменяем все, чтобы безопасно вернуться в режим x86.
    • Сложность: Жесткая. Не уверен все может быть сделано в VB6 (в частности, эта часть, связанная с стеком).
    • Преимущества: Однокомпонентный инжектор.
    • Недостатки: Если выполнено хорошо, нет.
    • поток Псевдо код/​​программы: Вы должны прочитать статью на http://rce.co/knockin-on-heavens-gate-dynamic-processor-mode-switching/ и посмотреть на коде (HeavenInjector), что было написано именно за то, что вы пытаетесь сделать, например, внутривенные библиотек в 64-битном процессов из 32-битного. Другим примером реализации этого метода будет WOW64Ext Library.

Будем надеяться, что после прочтения этого вы должны иметь представление о том, что попробовать следующий.

+0

Несколько комментариев: ** 1) ** Я просмотрел [код W64oWoW64] (https://github.com/georgenicolaou/W64oWoW64/blob/master/W64WoW64/w64wow64.c) (библиотека, используемая HeavenInjector) , а часть стека - это просто вопрос сохранения значения esp, выровняйте его по 8-байтовой границе, и как только мы закончим восстановление сохраненного значения esp, все это входит в объем наших 32-битных-> 64- > 32-битный код/​​thunk (я думал, что это связано с вызовом 'ZwCreateSection()', чтобы создать раздел для нового стека и манипулировать TIB нашего потока VB6 для замены указателей на стек). Было бы хорошим упражнением для того, чтобы порт базы библиотеки на VB6 один день. – johnwait

+0

_ (продолжение) _ ** 2) ** На самом деле есть четвертый вариант, и это будет переписывать/переносить ваш инжектор на 64-битный код, но это будет за пределами области вашего вопроса. Если вам интересно, я нашел [код здесь] (https://github.com/juntalis/project52a/blob/master/injector/src/injdll32.c), иллюстрирующий один из способов ввода 32-разрядной DLL из 64-битный процесс, который является частью (библиотеки?), Которая называется [Project52a] (https://github.com/juntalis/project52a). Хотя, возможно, есть и другие, лучшие примеры этого. – johnwait

0

Проверьте, если вы получаете идентификатор процесса на всех.

Если я правильно помню (и я пробовал это раньше), вы не можете получить список 64-битных процессов из 32-разрядного, используя только API; поэтому ваше приложение VB6 будет видеть только 32-битные процессы. Вам нужен (другой) 64-разрядный помощник, чтобы предоставить вам список 64-битных и 32-разрядных идентификаторов процессов, которые вы сможете использовать.

РЕДАКТИРОВАТЬ # 1: В документации CreateToolhelp32Snapshot() упоминает:

Если указанный процесс представляет собой 64-битный процесс, и вызывающий абонент является 32-разрядного процесса, эта функция терпит неудачу и последний код ошибки: ERROR_PARTIAL_COPY (299).

CORRECTION: Ненужные, так как вы вызываете CreateToolhelp32Snapshot(), без указанного процесса включить в снимок (т.е. второй аргумент пустой)

Вы все еще можете проверить, что инъекционные часть вашего программа работает при отладке, получая PID 64-битного Notepad процесса и подавая его вручную & непосредственно в InjectByPID().

РЕДАКТИРОВАТЬ # 2: Возможно, вы можете получить список процессов, которые включают 64-бит через WMI. См. this Super User question.

КОРРЕКЦИЯ:CreateToolhelp32Snapshot() перечисляет 64-битные и 32-битные процессы просто отлично. Я, наверное, перепутался с EnumProcesses().

+0

'CreateToolhelp32Snapshot()' отлично работает здесь и возвращает правильный PID notepad.exe 64bit. Этот код выше, отлично подходит для вас в Windows x64? Вы протестировали? –

+0

Мой плохой. Пожалуйста, уменьшите этот ответ. Первая проблема, которую я вижу, заключается в том, что вы получаете адрес 'LoadLibraryA()' в контексте процесса x86, следовательно, экспортируется сборкой x86 kernel32.dll, загружаемой VB6; это не будет одинаковым для сборки amd64. Путь к преодолению этого может заключаться в том, чтобы выделить память в удаленный x64-процесс, как вы уже это сделали, но затем напишите туда путь к DLL-пути * и * некоторый код начальной загрузки (amd64), который (1) найдет 'LoadLibraryW()', (2) загрузить DLL, которую нужно ввести, и (3) передать управление ей, и, наконец, вызвать этот код начальной загрузки, создав удаленный поток. – johnwait

+0

Вы могли бы сформулировать ответ с этими предложениями, пожалуйста? –

 Смежные вопросы

  • Нет связанных вопросов^_^