gpt4 book ai didi

c++ - 使用锁 xcmpchg16b _InterlockedCompareExchange128 发生读取访问冲突

转载 作者:行者123 更新时间:2023-11-30 16:35:55 24 4
gpt4 key购买 nike

我正在尝试使用锁 xcmpchg16b 来 Hook 函数。我尝试过大约 20 种不同的方法。

预期结果:

In real func
In hook func

调试构建结果:

Exception thrown at 0x..: 0xC0000005 Access violation reading 0xFFFFFFFFFFFFFFFF

我不确定为什么它试图从 0xFFFFFFFFFFFFFFFF 读取,没有任何指针指向那里。

发布版本中,它不会崩溃!但它也没有 Hook 该函数。

来源:

#include <stdio.h>
#include <Windows.h>

int RealFunc()
{
printf("In real func\n");
return 2;
}

int HookFunc()
{
printf("In hook func\n");
return 1;
}

int main()
{
DWORD dwOld;
if (!VirtualProtect(&RealFunc, 0x1000, PAGE_EXECUTE_READWRITE, &dwOld))
{
printf("Unable to make mem RWX.\n");
return 0;
}

RealFunc();

__declspec(align(16)) PVOID ProcAddress = &RealFunc;
__declspec(align(16)) LONG64 Restore[2];

Restore[0] = 0x0000000025ff9090; // nop, nop, jmp [rip + 0]
Restore[1] = (LONG64)&HookFunc;

_InterlockedCompareExchange128((LONG64*)ProcAddress, Restore[0], Restore[1], Restore);

RealFunc();

system("PAUSE");
return 0;
}

这里是函数文档:https://msdn.microsoft.com/en-us/library/windows/desktop/hh972640(v=vs.85).aspx

最佳答案

_InterlockedCompareExchange128((LONG64*)ProcAddress, 
Restore[0], Restore[1], Restore);

这当然是错误的。 if 寻找函数签名

unsigned char __cdecl InterlockedCompareExchange128(
_Inout_ LONGLONG volatile *Destination,
_In_ LONGLONG ExchangeHigh,
_In_ LONGLONG ExchangeLow,
_Inout_ LONGLONG *ComparandResult
);

第二个操作数是 ExchangeHigh,第三个操作数是 ExchangeLow - 因此必须是 Restore[1]、Restore[0],但不是 恢复[0],恢复[1]。另外,ComparandResult 必须保存原始函数数据。所以无法恢复

接下来还要注意,来自 MSDN:

The parameters for this function must be aligned on a 16-byte boundary; otherwise, the function will behave unpredictably on x64 systems.

但是哪些参数?全部 ?显然没有。例如 ExchangeHighExchangeLow 是按值传递的。我们可以在这里使用没有任何地址的直接值。所以谈论对齐对于第二个和第三个参数来说是毫无意义的。实际上,InterlockedCompareExchange128 被转换为lock cmpxchg16b 指令。来自英特尔手册

Note that CMPXCHG16B requires that the destination (memory) operand be 16-byte aligned.

因此只有 Destination 必须是 16 字节对齐。 ComparandResult - 否(它将被移动到 RCX:RBX 寄存器对)

so __declspec(align(16)) LONG64 Restore[2]; 您根本不需要 - 您可以将直接值传递给 InterlockedCompareExchange128。然后

__declspec(align(16)) PVOID ProcAddress = &RealFunc;

_InterlockedCompareExchange128((LONG64*)ProcAddress..

错误且毫无意义。 ProcAddress 的对齐有什么不同? point ProcAddress 所指向的内存必须是 16 字节对齐的。但不是 ProcAddress 本身。同样,我们在这里不需要任何临时变量。我们可以直接使用

_InterlockedCompareExchange128((LONG64*)RealFunc, ...)

当然RealFunc必须是16字节对齐的。否则我们会得到 0xC0000005 Access Violation Reading 0xFFFFFFFFFFFFFFFF 异常。

所以我猜想在 Debug模式下RealFunc不是16字节对齐的。

In a Release build, it doesn't crash! But it doesn't hook the function either.

不 Hook ,因为您在 ComparandResult 中使用了 Restore,也不异常(exception),因为 RealFunc 是随机 16 字节对齐的。

因为一般来说函数可以有任何地址,并且不能在 16 字节上对齐 - _InterlockedCompareExchange128 在这里根本没有用处。另外,这仅适用于 x64,不适用于 x86

代码(无论如何不是钩子(Hook)函数,如果RealFunc未在16字节上对齐)可以看起来像

int RealFunc()
{
printf("In real func\n");
return 2;
}

int HookFunc()
{
printf("In hook func\n");
return 1;
}

int xxx()
{
DWORD dwOld;

if (VirtualProtect(RealFunc, 2*sizeof(PVOID), PAGE_EXECUTE_READWRITE, &dwOld))
{
RealFunc();

#if defined(_M_X64)

if (!((LONG_PTR)RealFunc & 15))
{
LONG64 Comparand[2] = { ((LONG64*)RealFunc)[0], ((LONG64*)RealFunc)[1] };

InterlockedCompareExchange128((LONG64*)RealFunc, (LONG64)HookFunc, 0x0000000025ff9090, Comparand);
}
else
{
printf("bad function address %p\n", RealFunc);
}

#elif defined(_M_IX86)

static PVOID pvHookFunc = HookFunc;
LARGE_INTEGER Exchange = { 0x25ff9090, (LONG)&pvHookFunc };
LONG64 Comparand;

memcpy(&Comparand, RealFunc, sizeof(Comparand));
InterlockedCompareExchange64((LONG64*)RealFunc, Exchange.QuadPart, Comparand);

#else
#error not implemented
#endif

FlushInstructionCache(NtCurrentProcess(), RealFunc, 2*sizeof(PVOID));

if (dwOld != PAGE_EXECUTE_READWRITE)
{
VirtualProtect(RealFunc, 2*sizeof(PVOID), dwOld, &dwOld);
}

RealFunc();
}

return 0;
}

关于c++ - 使用锁 xcmpchg16b _InterlockedCompareExchange128 发生读取访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48695185/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com