2013-06-30 4 views
2

Я пытаюсь выполнить DLL-инъекцию, используя Ctypes Python. Я добавляю Olly к процессу, который я пытаюсь ввести, и поток, который я пытаюсь создать, дает ошибку: «ERROR_INVALID_PARAMETER 00000057». Я занимался некоторыми исследованиями, и я обнаружил, что, поскольку ошибка говорит о том, что один из моих параметров плох, когда я вызываю CreateRemoteThread. Я не могу понять, какой параметр является плохим, поскольку все значения, которые я посылаю, кажутся действительными. Я установил условную точку останова Олли при вызове LoadLibrary, и имя DLL и (полный) путь верны. Я также не вижу, как моя пользовательская dll загружается в пространство памяти процесса (в Olly). Мне интересно, связано ли это с тем, что моя dll и path являются unicode, когда я отправляю их в качестве параметра. Хотя условная точка останова на LoadLibrary говорит правильное имя и путь. Я также устанавливаю argtype, и, насколько я понимаю, ошибка будет выбрана, если это был неправильный тип, и попытался бы преобразовать его в правильный тип, когда это возможно.Ошибка_Invalid_Parameter Ошибка 57 при вызове CreateRemoteThread с Python 3.2 CTypes

import sys 
from ctypes import * 
from ctypes import wintypes 
import ctypes 

BYTE  = c_ubyte 
WORD  = c_ushort 
DWORD  = c_ulong 
LPBYTE = POINTER(c_ubyte) 
LPTSTR = POINTER(c_char) 
HANDLE = c_void_p 
PVOID  = c_void_p 
LPVOID = c_void_p 
UNIT_PTR = c_ulong 
SIZE_T = c_ulong 
LPTHREAD_START_ROUTINE = c_void_p 

class SECURITY_ATTRIBUTES(ctypes.Structure): 
_fields_ = [("nLength", DWORD), 
      ("lpSecurityDescriptor", LPVOID), 
      ("bInheritHandle", wintypes.BOOL)] 

LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES) 

kernel32.CreateRemoteThread.retype = wintypes.HANDLE 
kernel32.CreateRemoteThread.argtypes = [wintypes.HANDLE, LPSECURITY_ATTRIBUTES, ctypes.c_size_t, LPTHREAD_START_ROUTINE, wintypes.LPVOID, wintypes.DWORD, wintypes.LPDWORD] 

pid  = sys.argv[1] 
dll_path = sys.argv[2] #'myDLL.dll' 
dll_len = len(dll_path) * 2 #Multiplied by 2 so it would take into account the unicode characters 

h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid)) 
arg_address = kernel32.VirtualAllocEx(h_process, 0, dll_len, VIRTUAL_MEM, PAGE_READWRITE) 

written = c_ubyte(0) 
bSuccess = kernel32.WriteProcessMemory(h_process, arg_address, dll_path, dll_len, byref(written)) 
h_kernel32 = kernel32.GetModuleHandleW('kernel32.dll') 
h_loadlib = kernel32.GetProcAddress(h_kernel32, b"LoadLibraryW") 

thread_id = c_ulong(0) 

h_thread = kernel32.CreateRemoteThread(h_process, #404 
            None, 
            0, 
            h_loadlib,  #0x770a0000 
            arg_address, #0x770eef42 
            0, 
            byref(thread_id)) 

h_threadError = GetLastError() #This says ERROR 0 - Operation completed Successfully 

h_dllToHook = kernel32.GetModuleHandleW('myDLL.dll') #h_dllToHook returns '0' 
error = GetLastError()   #This says ERORR 0 - Operation completed Successfully 

Еще одна странная вещь заключается в том, что исполняемый файл я впрыскивается консольное приложение и печатает некоторый материал. DLL, в которую я вставляю, имеет экспортированную функцию, вызываемую из DLLMAIN, которая также печатает материал. Когда я проверяю консоль, она выглядит так, как будто она успешно запускается, когда материал в вложенной DLL также был распечатан. Также, когда я устанавливаю условную точку останова на CreateRemoteThread, она никогда не попадает. Итак, мои вопросы: если он успешно впрыскивается, так как кажется, 1) почему я не могу получить дескриптор вложенной DLL с использованием GetModuleHandleW и 2) почему не Ollydbg показывает, что вложенная DLL не отображается в процесс 'памяти. Я перешагиваю свой код и ломаю, так что это не похоже на то, что поток работает и выходит. Я изучаю какое-то время, поэтому любая помощь очень ценится! Благодарю.

ответ

1
  • Использовать ctypes.get_last_error вместо GetLastError. Для этого требуется опция use_last_error, например. WinDLL('kernel32.dll', use_last_error=True).
  • Не нужны шаги GetModuleHandleW и GetProcAddress. ctypes уже делает это для вас. Просто используйте kernel32.LoadLibraryW. Это зависит от того, что kernel32.dll всегда сопоставляется с одним и тем же базовым адресом в каждом процессе, что, на мой взгляд, верно для существующих версий Windows.
  • В общем случае вы должны учитывать нулевой ограничитель при копировании строки, например. использование len(dll_path) + 1. В этом случае вы записываете новую страницу памяти (4 KiB в системах x86 и x64), изначально изначально нули.
  • Я не уверен, как вы определили тип выделения VIRTUAL_MEM. Включает ли это MEM_COMMIT?
  • Остерегайтесь орфографических ошибок. Вы писали retype вместо restype для прототипа CreateRemoteThread, что означает, что возвращаемое значение по-прежнему является 32-разрядным значением по умолчанию C int.

Следующие работы для меня, загрузка DLL в процесс Python.

dllinject.py (ctypes ОПРЕДЕЛЕНИЯ):

import ctypes 
from ctypes import wintypes 

kernel32 = ctypes.WinDLL('kernel32.dll', use_last_error=True) 

PROCESS_VM_OPERATION = 0x0008 
PROCESS_VM_WRITE = 0x0020 
PROCESS_CREATE_THREAD = 0x0002 
MEM_COMMIT = 0x1000 
MEM_RELEASE = 0x8000 
PAGE_READWRITE = 0x0004 
INFINITE = -1 

SIZE_T = ctypes.c_size_t 
LPSIZE_T = ctypes.POINTER(SIZE_T) 
WCHAR_SIZE = ctypes.sizeof(wintypes.WCHAR) 
LPSECURITY_ATTRIBUTES = wintypes.LPVOID 
LPTHREAD_START_ROUTINE = wintypes.LPVOID 

class BOOL_CHECKED(ctypes._SimpleCData): 
    _type_ = "l" 
    def _check_retval_(retval): 
     if retval == 0: 
      raise ctypes.WinError(ctypes.get_last_error()) 
     return retval 

class LPVOID_CHECKED(ctypes._SimpleCData): 
    _type_ = "P" 
    def _check_retval_(retval): 
     if retval is None: 
      raise ctypes.WinError(ctypes.get_last_error()) 
     return retval 

HANDLE_CHECKED = LPVOID_CHECKED # not file handles 

kernel32.OpenProcess.restype = HANDLE_CHECKED 
kernel32.OpenProcess.argtypes = (
    wintypes.DWORD, # dwDesiredAccess 
    wintypes.BOOL, # bInheritHandle 
    wintypes.DWORD) # dwProcessId 

kernel32.VirtualAllocEx.restype = LPVOID_CHECKED 
kernel32.VirtualAllocEx.argtypes = (
    wintypes.HANDLE, # hProcess 
    wintypes.LPVOID, # lpAddress 
    SIZE_T,   # dwSize 
    wintypes.DWORD, # flAllocationType 
    wintypes.DWORD) # flProtect 

kernel32.VirtualFreeEx.argtypes = (
    wintypes.HANDLE, # hProcess 
    wintypes.LPVOID, # lpAddress 
    SIZE_T,   # dwSize 
    wintypes.DWORD) # dwFreeType 

kernel32.WriteProcessMemory.restype = BOOL_CHECKED 
kernel32.WriteProcessMemory.argtypes = (
    wintypes.HANDLE, # hProcess 
    wintypes.LPVOID, # lpBaseAddress 
    wintypes.LPCVOID, # lpBuffer 
    SIZE_T,   # nSize 
    LPSIZE_T)   # lpNumberOfBytesWritten _Out_ 

kernel32.CreateRemoteThread.restype = HANDLE_CHECKED 
kernel32.CreateRemoteThread.argtypes = (
    wintypes.HANDLE,  # hProcess 
    LPSECURITY_ATTRIBUTES, # lpThreadAttributes 
    SIZE_T,     # dwStackSize 
    LPTHREAD_START_ROUTINE, # lpStartAddress 
    wintypes.LPVOID,  # lpParameter 
    wintypes.DWORD,   # dwCreationFlags 
    wintypes.LPDWORD)  # lpThreadId _Out_ 

kernel32.WaitForSingleObject.argtypes = (
    wintypes.HANDLE, # hHandle 
    wintypes.DWORD)  # dwMilliseconds 

kernel32.CloseHandle.argtypes = (
    wintypes.HANDLE,) # hObject 

dllinject.ру (injectdll):

def injectdll(pid, dllpath): 
    size = (len(dllpath) + 1) * WCHAR_SIZE 
    hproc = hthrd = addr = None 
    try: 
     hproc = kernel32.OpenProcess(
      PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | 
      PROCESS_VM_WRITE, False, pid) 
     addr = kernel32.VirtualAllocEx(
      hproc, None, size, MEM_COMMIT, PAGE_READWRITE) 
     kernel32.WriteProcessMemory(
      hproc, addr, dllpath, size, None) 
     hthrd = kernel32.CreateRemoteThread(
      hproc, None, 0, kernel32.LoadLibraryW, addr, 0, None) 
     kernel32.WaitForSingleObject(hthrd, INFINITE) 
    finally: 
     if addr is not None: 
      kernel32.VirtualFreeEx(hproc, addr, 0, MEM_RELEASE) 
     if hthrd is not None: 
      kernel32.CloseHandle(hthrd) 
     if hproc is not None: 
      kernel32.CloseHandle(hproc) 

test.c:

#include <Windows.h>     
#include <stdio.h>     

BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, PVOID fImpLoad) 
{             
    switch (fdwReason) { 
     case DLL_PROCESS_ATTACH: 
      printf("DLL Attach\n"); 
      break; 
     case DLL_PROCESS_DETACH: 
      printf("DLL Detach\n"); 
    }               
    return TRUE;    
} 

демо:

>>> import sys 
>>> from subprocess import Popen, PIPE 
>>> from dllinject import injectdll 
>>> cmd = [sys.executable, '-c', 'import time; time.sleep(10)'] 
>>> p = Popen(cmd, stdout=PIPE); injectdll(p.pid, 'test.dll') 
>>> r = p.wait(); print(p.stdout.read().decode()) 
DLL Attach 
DLL Detach 

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

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