阅读:43471回复:4
KeI386AllocateGdtSelectors()这些未公开函数到底该怎么用?
我在程序中使用了这些函数,可编译老是不成功,错误报告为:
error LNK2001: unresolved external symbol \"__declspec(dllimport) long __stdcall KeI386AllocateGdtSelectors(unsigned short *,unsigned long)\" (__imp_?KeI386AllocateGdtSelectors@@YGJPAGK@Z) objfre\\i386\\callgate.sys() : error LNK1120: 1 unresolved externals 我想知道的是到底这个函数该怎么声明才能编译成功?我的函数声明是: NTKERNELAPI NTSTATUS KeI386AllocateGdtSelectors( PUSHORT pSelectorArray, ULONG NumberOfSelectors ); 有什么地方错了吗?如果谁再能提供个使用了这些函数的程序代码,那就太好了! |
|
沙发#
发布于:2002-01-03 21:10
非常感谢zdhe兄,你的回复非常正确,正确的函数声明应该为:
extern \"C\" NTKERNELAPI NTSTATUS KeI386AllocateGdtSelectors( PUSHORT pSelectorArray, ULONG NumberOfSelectors ); 现在可以编译了。真是气人,就这么个小失误,另我费解了好长时间,我的程序的文件后缀名为CPP。 |
|
板凳#
发布于:2002-01-02 03:16
既然是kennel方式下,声明时加个 extern \"C\"{}看看。
extern \"C\"{ NTKERNELAPI NTSTATUS KeI386AllocateGdtSelectors( PUSHORT pSelectorArray, ULONG NumberOfSelectors ); }; 不是大问题。 |
|
地板#
发布于:2002-01-02 02:52
我是指在DRIVER中用,但编译没成功
|
|
地下室#
发布于:2002-01-02 00:51
既然你使用了ntoskrnl.exe的export函数,又是undocumented,就不要指望静态连接了。(如果是是在driver中用,应该没有这个问题,ddk 提供的ntoskrnl.lib中有这个东东,虽然头文件中没有)
在usermode下,使用动态方式, typedef NTSTATUS ( * TYPE_KeI386AllocateGdtSelectors)( PUSHORT pSelectorArray, ULONG NumberOfSelectors ); TYPE_KeI386AllocateGdtSelectors KeI386AllocateGdtSelectors=NULL; HMODULE hNtOsKrnl = GetModuleHandle(\"ntoskrnl\"); if (hNtOsKrnl ) { *(DWORD*)&KeI386AllocateGdtSelectors= (DWORD)GetProcAddress(hNtOsKrnl ,\"KeI386AllocateGdtSelectors\"); .... } 如果只是想作ring3->ring0切换的机能,仔细找一找,这样的文章不少。 不使用你说的那个函数的一个比较晦涩的实装是 (机能是从ring3->ring0, 把page 属性从Read改成writable, 事实上是自己emum gdt.) long CallRing0(PVOID pvRing0FuncAddr, PVOID pvAddr, DWORD dwPageProtection) { GDT_DESCRIPTOR *pGDTDescriptor; GDTR gdtr; long Result; _asm Sgdt [gdtr] // Skip the null descriptor pGDTDescriptor = (GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8); // Search for a free GDT descriptor for (WORD wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++) { if (pGDTDescriptor->Type == 0 && pGDTDescriptor->System == 0 && pGDTDescriptor->DPL == 0 && pGDTDescriptor->Present == 0) { // Found one ! // Now we need to transform this descriptor into a callgate. // Note that we\'re using selector 0x28 since it corresponds // to a ring 0 segment which spans the entire linear address // space of the processor (0-4GB). CALLGATE_DESCRIPTOR *pCallgate; pCallgate = (CALLGATE_DESCRIPTOR *) pGDTDescriptor; pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr); pCallgate->Selector = 0x28; pCallgate->ParamCount = 0; pCallgate->Unused = 0; pCallgate->Type = 0xc; pCallgate->System = 0; pCallgate->DPL = 3; pCallgate->Present = 1; pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr); // Prepare the far call parameters WORD CallgateAddr[3]; CallgateAddr[0] = 0x0; CallgateAddr[1] = 0x0; CallgateAddr[2] = (wGDTIndex << 3) | 3; // Please fasten your seat belts! // We\'re about to make a hyperspace jump into RING 0. _asm { Mov ECX, [pvAddr] Mov EDX, [dwPageProtection] Cli Call FWORD PTR [CallgateAddr] Sti Mov DWORD PTR [Result], EAX } // Now free the GDT descriptor MemSet(pGDTDescriptor, 0, 8); return Result; } // Advance to the next GDT descriptor pGDTDescriptor++; } // Whoops, the GDT is full return 0; } 来源 // ----------------------------------- // // APISpy32 v3.0 // // Copyright 2000 Yariv Kaplan // // www.internals.com // // ----------------------------------- // |
|