簡體   English   中英

使用鎖xcmpchg16b _InterlockedCompareExchange128讀取訪問沖突

[英]Read access violation using lock xcmpchg16b _InterlockedCompareExchange128

我正在嘗試使用xcmpchg16b鎖定鈎子函數。 我已經嘗試了大約20種不同的方法。

預期結果:

In real func
In hook func

調試生成的結果:

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

我不確定為什么要嘗試從0xFFFFFFFFFFFFFFFFFF讀取,沒有指針去那里。

發布版本中,它不會崩潰! 但是它也沒有鈎住函數。

資源:

#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/zh-cn/library/windows/desktop/hh972640(v=vs.85).aspx

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

這當然是錯誤的。 如果尋找功能簽名

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

第二個操作數是ExchangeHigh和第三是ExchangeLow -因此必須Restore[1], Restore[0]但不Restore[0], Restore[1] 並且ComparandResult必須包含原始函數數據。 因此它不能Restore

還要注意下一個來自MSDN的內容:

此函數的參數必須在16字節邊界上對齊; 否則,該功能在x64系統上將無法正常運行。

但是哪些參數呢? 全部? 顯然沒有。 例如, ExchangeHighExchangeLow通過值傳遞。 我們可以在這里使用完全沒有任何地址的直接值。 因此,對於第二和第三參數,談論對齊是毫無意義的。 真正將InterlockedCompareExchange128轉換為lock cmpxchg16b指令。 從英特爾手冊

請注意, CMPXCHG16B要求目標(存儲器)操作數為16字節對齊。

因此只有Destination必須是16字節對齊的。 ComparandResult不(它將移至RCX:RBX寄存器對)

所以__declspec(align(16)) LONG64 Restore[2]; 您完全不需要-您可以將直接值傳遞給InterlockedCompareExchange128 然后

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

_InterlockedCompareExchange128((LONG64*)ProcAddress..

錯誤和毫無意義。 ProcAddress哪個對齊不同? ProcAddress 指向的內存必須對齊16個字節。 但不是ProcAddress本身。 同樣,我們在這里不需要任何臨時變量。 我們可以直接使用

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

當然, RealFunc必須對齊16字節。 否則,我們將獲得0xC0000005 Access violation reading 0xFFFFFFFFFFFFFFFF異常。

所以我想在調試模式下RealFunc不是16字節對齊的。

在發布版本中,它不會崩潰! 但是它也沒有鈎住函數。

不會鈎,因為您在原位使用ComparandResult Restore ,也沒有異常,因為RealFunc是隨機的16字節對齊。

因為一般情況下函數可以有任何地址,並且不能以16個字節對齊_InterlockedCompareExchange128在這里_InterlockedCompareExchange128沒有用。 這也僅適用於x64 ,不適用於x86

代碼(如果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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM