.net 4.0 代码注入 (C# & C++)
首先写一个注入用的 DLL:
// stdafx.h
#include <objbase.h>
#include <MetaHost.h>
#include <cassert>
// ProxyDll.cpp
#define ASSEMBLY_NAME L"Launcher.exe"
#define LOADER_TYPE L"moe.jixun.Inject"
#define LOADER_FUNCTION L"Init"
__declspec(dllexport) void Bootstrap() {
CoInitializeEx(0, COINIT_MULTITHREADED);
ICLRMetaHost *pMetaHost = nullptr;
HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
ICLRRuntimeInfo *pRuntimeInfo = nullptr;
pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&pRuntimeInfo);
ICLRRuntimeHost *pClrRuntimeHost = nullptr;
pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pClrRuntimeHost);
pClrRuntimeHost->Start();
DWORD dReturnValue;
hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(ASSEMBLY_NAME, LOADER_TYPE, LOADER_FUNCTION, L"Test", &dReturnValue);
assert(hr == S_OK);
}
因为 .net 的 exe 可以当做库来用,可以直接把代码写到我们的 exe 然后注入进去执行。
当然,你可能需要修改上述代码使其寻找 dll 所在的目录。
然后便是编写启动器,负责寻找注入程序以及注入后执行的代码。
// 加入目标函数的引用,可以快速定位
// 或者
namespace moe.jixun
{
public class Inject
{
static HammerCheatInit () {
// 此处初始化
}
public static int Init(String pwzArgument)
{
return 1;
}
// 测试用函数
private int Empty()
{
return 1;
}
// 获取函数的机器码地址
private static void Test()
{
Type typeCheatInit = typeof(HammerCheatInit);
MethodInfo empty = typeCheatInit.GetMethod("Empty", BindingFlags.NonPublic | BindingFlags.Instance);
RuntimeHelpers.PrepareMethod(empty.MethodHandle);
var addr = empty.MethodHandle.GetFunctionPointer().ToInt32();
MessageBox.Show(addr.ToString("x"));
}
}
}
如果目标是调试构建版,那么读出来的是一个跳转,需要再读取相对地址。
C# 注入 DLL 到其它进程的代码网上很多,我就不提供了..
以上。
参考
- StackOverflow: C++ 对 .net 4.0 进行操作
- .net 代码注入的基本概念
- 更多的 StackOverflow 帖子