首页 > 编程语言 > 详细

win32 - 将线程重定向到另一个函数(附带Suspend的解释)

时间:2020-10-15 22:12:47      阅读:32      评论:0      收藏:0      [点我收藏+]

Suspend: 挂起指定的线程

备注:不要永远挂起线程, 因为在Win32中,进程堆是线程安全的对象,并且由于在不访问堆的情况下很难在Win32中完成很多工作,因此在Win32中挂起线程极有可能使进程死锁。


 

那么,为什么首先还要有SuspendThread函数呢?

调试器在调试过程中使用它冻结进程中的所有线程。调试器还可以使用它冻结进程中除一个线程之外的所有线程,因此您一次只能专注于一个线程。由于调试器是一个独立的进程,因此不会在调试器中创建死锁。

Link: Why you should never suspend a thread

并且我们不应该用来Suspend-Thread同步两个线程,因为没有实际的同步保证。发生的是Suspend-Thread信号通知调度程序挂起线程并立即返回。如果调度程序正忙于执行其他操作,则它可能无法立即处理挂起请求,因此被挂起的线程将在借来的时间上运行,直到调度器处理挂起请求为止,此时它实际上已被挂起。

如果要确保线程确实被挂起,则需要执行同步操作,该操作取决于线程被挂起的事实。因为这是操作的先决条件,并且由于操作是同步的,所以这会强制处理该暂停请求,您知道在返回时肯定已经发生了暂停。

传统的做法是调用Get-Thread-Context,因为这需要内核从被挂起的线程的上下文中读取,这首先需要将上下文保存在该位置,而该前提是必须先将线程挂起。


 

一些代码:

#pragma pack(push, 1)
struct myByteCode
{
    BYTE push;
    DWORD pushValue;
    BYTE call;
    INT32 callOffset;
    BYTE ret;
};
#pragma pack(pop)

// allocate executable page for shellcode
struct myByteCode* mem = (struct myByteCode*) VirtualAlloc(0, sizeof(struct myByteCode), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!mem)
{
    // error handling...
}

// copy shellcode to page
mem->push = 0x68;
mem->pushValue = (DWORD) ThreadCallbackParameter;
mem->call = 0xE8;
mem->callOffset = ((INT_PTR)ThreadCallback) - ((INT_PTR)(&mem->ret));
mem->ret = 0xC3;

DWORD ignored;
if (!VirtualProtect(mem, sizeof(struct myByteCode), PAGE_EXECUTE, &ignored))
{
    // error handling...
}

FlushInstructionCache(GetCurrentProcess(), mem, sizeof(struct myByteCode));

// redirect thread to shellcode
...

需要FlushInstructionCache()在执行分配的内存之前先对其进行调用而且,您还应该READ/WRITE(用VirtualProtect)从内存中删除这些标志,以避免恶意代码劫持您的Shell代码来执行其他操作。

Link: Redirecting thread to another function

win32 - 将线程重定向到另一个函数(附带Suspend的解释)

原文:https://www.cnblogs.com/strive-sun/p/13821547.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!