.net CLR方法挂钩

.net CLR方法挂钩,.net,c++-cli,hook,clr,.net,C++ Cli,Hook,Clr,我想钩住一个CLR方法,在我的例子中,我试图钩住AppDomain->Load(字节[]) 我尝试了几个我能找到的钩住自写类方法的例子,但它们似乎都不适用于CLR方法。所以我尝试使用AppDomain::CurrentDomain对象的vtable挂钩,这在理论上似乎是可行的。 但是,无论何时调用我的方法,它都会在内部某个地方崩溃,WinDBG会显示以下错误: 例外代码:c0000005(访问冲突) 尝试执行不可执行地址000000 D8010200 堆栈: 0000000000 1AECE00

我想钩住一个CLR方法,在我的例子中,我试图钩住AppDomain->Load(字节[])

我尝试了几个我能找到的钩住自写类方法的例子,但它们似乎都不适用于CLR方法。所以我尝试使用AppDomain::CurrentDomain对象的vtable挂钩,这在理论上似乎是可行的。 但是,无论何时调用我的方法,它都会在内部某个地方崩溃,WinDBG会显示以下错误:

例外代码:c0000005(访问冲突)
尝试执行不可执行地址000000 D8010200
堆栈:
0000000000 1AECE0000007FE927E20DA cppclihook!DomainBoundILStubClass.IL_STUB_ReversePInvoke+0x8a
0000000000 1EE10 000007fe927e1a28 cppclihook_主模块+0x48
0000000000 1AEF20 000007fe927e1988 cppclihook!DomainBoundILStubClass.IL_STUB_PInvoke+0x68

我只需调用AppDomain->Load并在vs中检查生成的反汇编代码即可获得vtable偏移量,如下所示:

当前代码:

public delegate Reflection::Assembly^ CurrentDomain_LoadDelegate_Hook(AppDomain^ thisptr, array<uint8_t>^ data);
public delegate Reflection::Assembly^ CurrentDomain_LoadDelegate(array<uint8_t>^ data);
Reflection::Assembly^ (__clrcall* CurrentDomain_Load)(AppDomain^ thisptr, array<uint8_t>^ data);

Reflection::Assembly^ __clrcall CurrentDomain_Load_Hook(AppDomain^ thisptr, array<uint8_t>^ data)
{
System::Windows::Forms::MessageBox::Show("Hooked");

// calls jmp <clr.AssemblyNative::LoadImage>
return CurrentDomain_Load(thisptr, data);
}

void HookDomain(AppDomain^ domain)
{
    auto fp = gcnew CurrentDomain_LoadDelegate_Hook(CurrentDomain_Load_Hook);
    RuntimeHelpers::PrepareMethod(fp->Method->MethodHandle);

    auto gch = GCHandle::Alloc(fp);
    auto ip = Marshal::GetFunctionPointerForDelegate(fp);
    auto hookAddr = (uintptr_t)ip.ToPointer();

    // auto orig = gcnew CurrentDomain_LoadDelegate(domain, &AppDomain::Load);
    // RuntimeHelpers::PrepareMethod(orig->Method->MethodHandle);

    auto domainPtrHandle = System::Runtime::InteropServices::GCHandle::Alloc(domain);
    auto domainIntPtr = System::Runtime::InteropServices::GCHandle::ToIntPtr(domainPtrHandle);
    auto domainPtr = *(uintptr_t*)domainIntPtr.ToPointer();

    auto vtableAddr = *(uintptr_t***)domainPtr;
    auto funcAddr = vtableAddr[12];

    DWORD protect;
    VirtualProtect(funcAddr, sizeof(uintptr_t), PAGE_EXECUTE_READWRITE, &protect);
    // save orig addr
    // CurrentDomain_Load = ?
    *funcAddr = hookAddr;
    VirtualProtect(funcAddr, sizeof(uintptr_t), protect, &protect);
}

int main(int argc, char** argv)
{
    HookDomain(AppDomain::CurrentDomain);

    try
    {
        array<uint8_t>^ arr = gcnew array<uint8_t>(256);
        System::AppDomain::CurrentDomain->Load(arr);
    }
    catch(Exception^) {}

    return 0;
}
public delegate Reflection::Assembly^CurrentDomain\u LoadDelegate\u Hook(AppDomain^thisptr,数组^data);
公共委托反射::程序集^CurrentDomain\u加载委托(数组^data);
反射::程序集^;
反射::程序集^ clrcall CurrentDomain_Load_Hook(AppDomain ^thisptr,数组^data)
{
系统::Windows::窗体::MessageBox::显示(“挂钩”);
//调用jmp
返回CurrentDomain_负载(此PTR,数据);
}
void HookDomain(AppDomain^domain)
{
自动fp=gcnew CurrentDomain\u LoadDelegate\u Hook(CurrentDomain\u Load\u Hook);
RuntimeHelpers::PrepareMethod(fp->Method->MethodHandle);
自动gch=GCHandle::Alloc(fp);
自动ip=Marshal::GetFunctionPointerForDelegate(fp);
auto hookAddr=(uintptr_t)ip.ToPointer();
//auto orig=gcnew CurrentDomain\u LoadDelegate(域和AppDomain::Load);
//RuntimeHelpers::PrepareMethod(orig->Method->MethodHandle);
auto domainPtrHandle=System::Runtime::InteropServices::GCHandle::Alloc(域);
auto domainIntPtr=System::Runtime::InteropServices::GCHandle::ToIntPtr(domainPtrHandle);
auto domainPtr=*(uintptr_t*)domainIntPtr.ToPointer();
自动vtableAddr=*(uintpttr_t***)域ptr;
auto funcAddr=vtableAddr[12];
德沃德保护;
虚拟保护(funcAddr、sizeof(uintpttr)、PAGE\u EXECUTE\u READWRITE和protect);
//保存原始地址
//CurrentDomain_Load=?
*funcAddr=hookAddr;
虚拟保护(funcAddr、sizeof(uintptr)、protect和protect);
}
int main(int argc,字符**argv)
{
HookDomain(AppDomain::CurrentDomain);
尝试
{
数组^arr=gc新数组(256);
System::AppDomain::CurrentDomain->Load(arr);
}
捕获(异常^){}
返回0;
}
我实际上检查了原始加载方法中发生的事情,它似乎没有做任何特殊的事情:

当我在vtable调用中使用钩子方法时,在调用无效指针时,钩子方法在此崩溃:

我还尝试将AppDomain指针和钩子提供给本机DLL,使其指向只调用原始地址的本机函数。 因为它只生成一个JMP[原始加载],我希望它能工作,但它在网络调用的某个地方开始崩溃

我是错过了什么,还是做错了什么?
希望任何人都能帮助我。

汇编.Load
不是虚拟的,因此它没有vtable条目。我很确定您在这里有一个—您实际上想要实现什么?
程序集。Load
不是虚拟的,因此它没有vtable条目。我很确定你在这里有一个目标——你到底想要实现什么?