c# - (EasyHook) 在同一项目中无法识别 DLL
问题描述
如果这是一个愚蠢的问题,请道歉;我对 Visual Studio 并不太熟悉,也绝对不是新版本。
我正在尝试使用 EasyHook 从 Windows 应用程序中挂钩对 TextOutA 的调用,大致遵循本教程,在 Visual Studio 2019 中。(我 100% 确定它们是 TextOutA;反编译器输出也表明了这一点,并且我能够成功挂钩它们使用 C++。不幸的是,对于 EasyHook,C# 比 C++ 更受支持/记录。)
根据本教程,我在同一个解决方案中有一个控制台应用程序和一个类库作为两个项目。让 Visual Studio 解决方案完全编译有些坎坷——我不得不手动将 .csproj 文件编辑为 .NET Framework 4.8(根据这个问题),并且需要进行一些修改才能使其正常工作。但现在我担心我修修补补太多了。
会发生什么:代码编译没有错误和警告,并且看似成功运行。但是,似乎没有调用 DLL 中的任何内容。它的代码似乎都没有被执行,Run() 中的断点永远不会被命中,如果我完全摆脱 Run() 代码,它仍然可以编译。
到目前为止,这是控制台应用程序代码(文件名已编辑;此代码可能还有其他问题,但我必须运行它才能找出答案):
static void Main(string[] args)
{
string injectionLibrary = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "[name of DLL].dll");
Console.WriteLine(injectionLibrary);
try
{
Int32 processID = 0;
Process[] process = Process.GetProcessesByName("[process name]");
Console.Write(process[0]);
processID = process[0].Id;
EasyHook.RemoteHooking.Inject(
processID, // ID of process to inject into
injectionLibrary, // 32-bit library to inject (if target is 32-bit)
injectionLibrary, // 64-bit library to inject (if target is 64-bit)
null // the parameters to pass into injected library
// ...
);
Console.WriteLine("Injected, supposedly.");
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("There was an error while injecting into target: ");
Console.ResetColor();
Console.WriteLine(e.ToString());
}
Console.ReadKey();
}
}
}
这是类库:
namespace [DLL name]
{
public class MySimpleEntryPoint : EasyHook.IEntryPoint
{
public MySimpleEntryPoint(EasyHook.RemoteHooking.IContext context)
{
}
public void Run(EasyHook.RemoteHooking.IContext context)
{
Console.Write("Test");
var textOutHook = EasyHook.LocalHook.Create(
EasyHook.LocalHook.GetProcAddress("Gdi32.dll", "TextOutA"),
new TextOutDelegate(TextOut_Hook),
this);
textOutHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
}
[UnmanagedFunctionPointer(CallingConvention.StdCall,
CharSet = CharSet.Unicode,
SetLastError = true)]
delegate bool TextOutDelegate(IntPtr orig_handle, int x_value, int y_value, string output_string, int color);
[DllImport("gdi32.dll", CharSet = CharSet.Unicode, EntryPoint = "TextOutA", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
static extern bool TextOutA(IntPtr orig_handle, int x_value, int y_value, string lpString, int color);
bool TextOut_Hook(IntPtr orig_handle, int x_value, int y_value, string output_string, int color)
{
// We aren't going to call the original at all... YET
Console.Write("...intercepted...");
return false;
}
}
}
该进程的控制台输出与预期一致,路径的输出也是如此:C:\Users[my username]\source\repos[name of project]\build\net48\ [name of DLL].dll --这确实是 dll 输出到的地方。但是,如上所述, Run() 中的任何内容似乎实际上都没有被调用, TextOutA 肯定没有被抑制,等等。
我试过的:
- 将 .dll 和类库项目(分别)添加为对控制台应用程序的引用
- 将 .dll 和可执行文件设置为输出到同一文件夹
- 调整应该获得路径的代码行
- 将此代码与我能找到的基本上任何可比较的 EasyHook 项目进行比较,似乎没有任何问题
- 从控制台应用程序而不是钩子中调用 GetProcAddress;它按预期工作,所以问题似乎不是那个
任何帮助将非常感激。
解决方案
根据我的评论回答。
您的示例中发生了两件事:
- 当 Run 退出时,您的钩子可能会被 GC 清理并因此被卸载
- 当 Run 退出时,EasyHook 将卸载您的程序集
托管的 EasyHook 帮助程序库在新线程中EasyLoad
运行您的IEntryPoint.Run
方法并等待它退出。当方法退出时,程序集被卸载等。
因此,您应该在Run
方法的末尾添加一个 while 循环,以防止它退出,直到您完成钩子。
public void Run(EasyHook.RemoteHooking.IContext context)
{
// install hooks
...
while (true) {
Thread.Sleep(500);
// optionally perform a check to see if should break
}
// uninstall hooks / cleanup / etc
}
推荐阅读
- matlab - MATLAB:识别最大值和最小值并相应地拆分数据
- python - Python statsmodels:回归摘要,如何获取参考虚拟变量的 p 值?
- python - Python-如何绘制非数值时间序列
- react-native - 如何检查 fetch POST 中的主体是否已发送到反应原生的 API?
- php - 将变体价格添加到 Woocommerce 中的可变产品下拉项目名称
- java - 如何在 Cell Factory 中以编程方式选择 ComboBox 值?
- java - jvm在创建非文字大小的数组时如何分配内存
- javascript - 使用nodejs在多个文件中初始化firebase应用程序
- ruby-on-rails - 带有 where 子句的 Rails 表
- arrays - Swift 中 Array 的简单“拼接”类型方法?