«访问控制»发生在编译时,仅用于 c++ 代码。你甚至不需要编辑机器代码——你可以很容易地从汇编语言中调用私有方法——所以这表明这仅适用于 c++ 限制。当然,没有任何额外的机器代码可以在运行时控制它——这根本不可能控制谁调用方法。
简单的演示。注意函数名称,它如何损坏取决于 x86 或 x64 编译以及编译器可能 - 我的 CL 编译器和 x64 平台 bat 演示,它可以轻松更改为 x86 或其他编译器
c++代码
class Print
{
public:
void printPublic();
private:
void printPrivate();
};
// must be not inline or referenced from c++ code or will be droped by compiler!
void Print::printPrivate()// thiscall
{
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
void Print::printPublic()// thiscall
{
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
extern "C"
{
// stub impemeted in asm
void __fastcall Print_printPrivate(Print* This);
void __fastcall Print_printPublic(Print* This);
};
Print p;
//p.printPrivate();//error C2248
p.printPublic();
Print_printPrivate(&p);
Print_printPublic(&p);
和asm代码(对于ml64)
_TEXT segment 'CODE'
extern ?printPrivate@Print@@AEAAXXZ:proc
extern ?printPublic@Print@@QEAAXXZ:proc
Print_printPrivate proc
jmp ?printPrivate@Print@@AEAAXXZ
Print_printPrivate endp
Print_printPublic proc
jmp ?printPublic@Print@@QEAAXXZ
Print_printPublic endp
_TEXT ENDS
END
还请注意,仅对于 x86,所有 c++ 方法都使用 thiscall 调用约定 - ECX 寄存器中的第一个参数 this 和堆栈中的下一个参数__stdcall - 所以如果方法没有参数(真的是一个 this ),我们可以将 __fastcall 用于 asm 函数,如果存在我们需要的参数将 EDX 推送到汇编程序存根中。对于 x64 没有这个问题 - 这里只有一个调用约定,但所有这些都与主要问题无关。
带有额外参数的 x86 代码示例,用于展示如何将 __fastcall 转换为 __thiscall
class Print
{
public:
void printPublic(int a, int b)// thiscall
{
DbgPrint("%s<%p>(%x, %x)\n", __FUNCTION__, this, a, b);
}
private:
void printPrivate(int a, int b);
};
// must be not inline or referenced from c++ code or will be droped by compiler!
void Print::printPrivate(int a, int b)// thiscall
{
DbgPrint("%s<%p>(%x, %x)\n", __FUNCTION__, this, a, b);
}
extern "C"
{
// stub impemeted in asm
void __fastcall Print_printPrivate(Print* This, int a, int b);
void __fastcall Print_printPublic(Print* This, int a, int b);
};
Print p;
//p.printPrivate(1,2);//error C2248
p.printPublic(1, 2);
Print_printPrivate(&p, 1, 2);
Print_printPublic(&p, 1, 2);
和asm
.686p
_TEXT segment
extern ?printPublic@Print@@QAEXHH@Z:proc
extern ?printPrivate@Print@@AAEXHH@Z:proc
@Print_printPrivate@12 proc
xchg [esp],edx
push edx
jmp ?printPrivate@Print@@AAEXHH@Z
@Print_printPrivate@12 endp
@Print_printPublic@12 proc
xchg [esp],edx
push edx
jmp ?printPublic@Print@@QAEXHH@Z
@Print_printPublic@12 endp
_TEXT ends
end