Python 3.x 使用Python 3.2 CTypes调用CreateRemoteThread时出现错误\u无效\u参数错误57

Python 3.x 使用Python 3.2 CTypes调用CreateRemoteThread时出现错误\u无效\u参数错误57,python-3.x,ctypes,dll-injection,Python 3.x,Ctypes,Dll Injection,我正在尝试使用Python的Ctypes执行DLL注入。我将Olly附加到我尝试注入的进程,我尝试创建的线程给出错误“error\u INVALID\u PARAMETER 00000057”。我一直在做一些研究,我发现当我调用CreateRemoteThread时,错误表明我的一个参数是错误的。我似乎无法找出哪个参数是坏的,因为我发送的所有值似乎都是有效的。我在调用LoadLibrary时设置了一个Olly条件断点,并且dll名称和(完整)路径是正确的。我也没有看到我的自定义dll加载到进程的

我正在尝试使用Python的Ctypes执行DLL注入。我将Olly附加到我尝试注入的进程,我尝试创建的线程给出错误“error\u INVALID\u PARAMETER 00000057”。我一直在做一些研究,我发现当我调用CreateRemoteThread时,错误表明我的一个参数是错误的。我似乎无法找出哪个参数是坏的,因为我发送的所有值似乎都是有效的。我在调用LoadLibrary时设置了一个Olly条件断点,并且dll名称和(完整)路径是正确的。我也没有看到我的自定义dll加载到进程的内存空间中(在Olly中)。我想知道这是否与我的dll和路径作为参数发送时是unicode有关。尽管LoadLibrary上的条件断点显示了正确的名称和路径。我还设置了argtype,据我所知,如果它是错误的类型,就会抛出一个错误,并且它会在可能的情况下尝试将其转换为正确的类型

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)为什么我不能使用GetModuleHandleW获得注入DLL的句柄;2)为什么Ollydbg没有显示注入DLL没有映射到进程的内存空间。我正在单步执行我的代码并中断,因此不像线程正在运行并退出。我已经研究了一段时间,所以非常感谢您的帮助!谢谢。

  • 使用
    ctypes.get_last_error
    而不是
    GetLastError
    。这需要
    use\u last\u error
    选项,例如
    windell('kernel32.dll',use\u last\u error=True)
  • GetModuleHandleW
    GetProcAddress
    步骤是不必要的。ctypes已经为您完成了这项工作。只需使用
    kernel32.LoadLibraryW
    。这取决于kernel32.dll在每个进程中始终映射到相同的基址,我认为这对于现有版本的Windows是正确的
  • 通常,在复制字符串时,应考虑空终止符,例如使用
    len(dll_path)+1
    。在本例中,您正在提交一个新的内存页(x86和x64系统上为4kib),它最初为全零
  • 我不确定您是如何定义
    VIRTUAL\u MEM
    分配类型的。这是否包括
    MEM_COMMIT
  • 注意拼写错误。您为
    CreateRemoteThread
    的原型编写了
    retype
    而不是
    restype
    ,这意味着返回值仍然是默认的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
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)
#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
dllinject.py(
injectdll
):

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
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)
#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
test.c:

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
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)
#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