我正在尝试使用Python的Ctypes执行DLL注入。我将Olly附加到我正在尝试注入的进程中,并且我尝试创建的线程会出现错误“ERROR_INVALID_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没有映射到进程'记忆空间。我正在逐步执行我的代码并打破,因此它不像线程正在运行并退出。我已经研究了一段时间,所以任何帮助都非常感谢!感谢。
答案 0 :(得分: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
。在这种情况下,您将提交一个新的内存页面(在x86和x64系统上为4 KiB),这最初都是零。 VIRTUAL_MEM
分配类型的。这包括MEM_COMMIT
?retype
的原型编写了restype
而不是CreateRemoteThread
,这意味着返回值仍然是默认的32位C int
。 以下适用于我,将DLL加载到Python进程中。
dllinject.py(ctypes defintions):
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.py(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