这可能是一个非常简单的问题,但不知何故,我无法完全理解答案,而且我也找不到关于该主题的任何好的相关文档。
因此,我尝试使用 Python 的 ctypes 模块和 ctypes.windll.kernel32 类中的 CreateThread 方法进行 PoC(在程序的内存空间中进行一些 shellcode 注入)
根据 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))
更新:这是一个示例代码,这个实现可以在网上看到:
请注意上面链接的脚本行中提到的注释:
# _Out_opt_ LPDWORD lpThreadId // NULL, so the thread identifier is not returned.
看来作者在评论 CreateThread 函数调用的参考时可能是错误的。
假设: 根据 Mark's answer 中提到的评论,ThreadID 和 ThreadHandle 是不同的,并且通过传入 ctypes.pointer(ctypes.c_int(0)) 而不仅仅是普通的 ctypes.c_int(0) (NULL) 意味着在 int 0 位置,将存储线程 ID。有人可以证实这个假设吗?