0

Ntdll.dllからエクスポートされたメソッドを呼び出すのに問題があります

VS2012のデバッグモードでは、次のようになります。

実行時チェックの失敗#0-ESPの値は、関数呼び出し全体で適切に保存されませんでした。これは通常、ある呼び出し規約で宣言された関数を、別の呼び出し規約で宣言された関数ポインターで呼び出した結果です。

これは私が使用したコードです(x86プラットフォーム、Windows 7)。

#include "stdafx.h"
#include <Windows.h>

typedef NTSTATUS (* NTAPI  ZwClose)(HANDLE handle);

int _tmain(int argc, _TCHAR* argv[])
{
    ZwClose close = (ZwClose) ::GetProcAddress(GetModuleHandle(L"ntdll.dll"), "ZwClose");
    close(INVALID_HANDLE_VALUE);  // Error happens here
        return -1;
}

私が読んだことから、それはうまくいくはずです。また、代替の呼び出し規約として__cdeclと__fastcallを試しましたが、何も機能しませんでした。

4

1 に答える 1

4

あなたは悪いキャスティングをしました、それは次のようになります:

typedef NTSTATUS (NTAPI* ZwClose)(HANDLE handle);

あなたの宣言は、Cの慣習に従うように関数へのポインタを作りました。Cの呼び出し規約は、スタックが呼び出し元によって修正されることを除いて、STDCALLと同じです。

;C
push arg1
call fun
add esp, 4 
...

; STDCALL

push arg1
call func

逆アセンブルでは、ZwCloseを呼び出した後、Espの値がチェックされていることがわかります。ZwCloseの呼び出しはC規則であったため、esp値は呼び出し元と、エラーofcを引き起こす関数自体によって修正されました。

000F14C4  mov         esi,esp  
000F14C6  push        0FFFFFFFFh  
000F14C8  call        dword ptr [close]  
000F14CB  add         esp,4  
000F14CE  cmp         esi,esp  
000F14D0  call        @ILT+380(__RTC_CheckEsp) (0F1181h) ; Run-Time Check Failure #0
于 2013-03-02T15:07:42.187 に答える