Python - Ctype.windll.kernel32.CreateThread 参数值

标签 python c ctypes kernel32 createthread

这可能是一个非常简单的问题,但不知怎的,我就是无法理解答案,而且我也找不到关于此类主题的任何好的相关文档。

因此,我尝试使用 Python 的 ctypes 模块和 ctypes.windll.kernel32 类中的 CreateThread 方法进行 PoC(在程序的内存空间内进行一些 shellcode 注入(inject))

根据msdn文档CreateThread这7个参数是:

  • 指向安全属性的指针
  • 初始堆栈大小
  • 指向起始地址的指针
  • 指向任何参数的指针
  • 创建标志
  • 指向接收线程标识符的值的指针

所有使用python调用c风格函数和库的例子都是这样的:

thread_handle = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
                ctypes.c_int(0),
                ctypes.c_int(ptr),
                ctypes.c_int(0),
                ctypes.c_int(0),
                ctypes.pointer(ctypes.c_int(0)))

有人可以解释一下为什么最后一个参数被用作ctypes.pointer(c_int0),而另一个空指针的整数0常量值被用作其他参数。 (例如ctypes.c_int(0))

更新:这是一个示例代码,这个实现在网上随处可见:

createThread function call in python第786行

注意上面链接的脚本行,提到的注释:

  #   _Out_opt_ LPDWORD  lpThreadId  // NULL, so the thread identifier is not returned.

看来作者在注释 CreateThread 函数调用的引用时可能是错误的。

假设: 根据 Mark 的回答中提到的评论,ThreadID 和 ThreadHandle 是不同的,通过传入 ctypes.pointer(ctypes.c_int(0)) 而不是简单的 ctypes.c_int(0) (NULL) 意味着在int 0位置,将存储线程ID。有人可以证实这个假设吗?

最佳答案

最后一个参数实例化一个 C 整数 (c_int(0)) 并将其作为指针传递。这与最后一个参数定义松散匹配。它应该是一个 DWORD,通常定义为 unsigned long (ctypes 中的 c_ulong)。使用ctypes.byref比创建指针更有效。该参数用于将线程ID作为输出参数返回,因此需要正确的C类型实例的地址来存储该ID。

这是一个使用 ctypes 显式定义每个函数的输入/输出的工作示例。请注意,ctypeswintypes 中预定义了 Windows 类型:

import ctypes as c
from ctypes import wintypes as w

LPTHREAD_START_ROUTINE = c.WINFUNCTYPE(w.DWORD,w.LPVOID)
SIZE_T = c.c_size_t

k32 = c.WinDLL('kernel32')
test = c.WinDLL('test')

CreateThread = k32.CreateThread
CreateThread.argtypes = w.LPVOID,SIZE_T,LPTHREAD_START_ROUTINE,w.LPVOID,w.DWORD,w.LPDWORD
CreateThread.restype = w.HANDLE

WaitForSingleObject = k32.WaitForSingleObject
WaitForSingleObject.argtypes = w.HANDLE,w.DWORD
WaitForSingleObject.restype = w.DWORD

sa = None  # No security specified.  None == NULL pointer.
stack = 0  # Use default stack
start = LPTHREAD_START_ROUTINE(test.func)
param = 0x12345
flags = 0 # start thread immediately
tid = w.DWORD()
h = CreateThread(sa,stack,start,param,flags,c.byref(tid))
WaitForSingleObject(h,1000) # wait for the thread to exit.

以下是作为线程运行的简单 C 函数的代码:

#include <stdio.h>

__declspec(dllexport) unsigned long __stdcall func(void* p)
{
    printf("%p\n",p);
    return 0;
}

这是输出:

0000000000012345

关于Python - Ctype.windll.kernel32.CreateThread 参数值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50576770/

相关文章:

python - 使用 subprocess 模块的字符串参数

python - 我收到预期错误 <class 'openpyxl.styles.fills.Fill' > 使用 pandas read_excel 读取 excel 文件

c - 打印每个数字中包含 0 的数字(仅自然数)

Python:将for循环中的索引合并为列表名称的一部分

python - Atom 模块导入错误

C代码优化,流畅的功能

从 C 文件更改头文件中结构变量中的 char 数组会弄乱数组

python - Ctypes中的TA-Lib,帮助调用函数

python - 有没有办法通过ctypes加载存储在头文件中的常量值?

python - 将 swig python 'double *' 对象读入 numpy(也许通过 ctypes?)