首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有原始函数调用的EasyHook

具有原始函数调用的EasyHook
EN

Stack Overflow用户
提问于 2011-05-19 20:47:14
回答 2查看 2.7K关注 0票数 1

我正在开发一个应用程序,它使用EasyHook库向所需的进程注入代码,并拦截来自特定dll的调用。在我的例子中,库是Oracle,OCI.dll。我希望拦截已执行的sql语句,以便在客户端创建sql查询日志。以前我使用的是微软之绕道(2.1版),但它的许可证不允许商业使用,3.0版花费很大。我开始使用EasyHook库。我在交付的示例中更改了代码,该示例从kernel32.dll中截取函数CreateFileW,并将其调整为与oci.dll中的函数OCIStmtFetch2一起工作。

我有头文件或oci库,因为我知道确切的函数参数和返回类型。根据头文件,签名是:

剑OCIStmtFetch2 ( OCIStmt *stmtp,OCIError *errhp,ub4 nrow,ub2方位,ub4 scrollOffset,ub4模式);

根据Oracle提供的其他头文件,OCIStmt是一个结构,OCIError是处理错误函数。ub2和ub4是无符号短(16位)和无符号int (32位)的类型。EasyHook库注入的代码如下所示(一些函数名与样例FileMonInject相同):

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.InteropServices;
using EasyHook;

namespace FileMonInject
{
    public class Main : EasyHook.IEntryPoint
    {
        FileMon.FileMonInterface Interface;
        LocalHook CreateFileHook;
        Stack<String> Queue = new Stack<String>();
        public Main(
            RemoteHooking.IContext InContext,
            String InChannelName)
        {
            // connect to host...
            Interface = RemoteHooking.IpcConnectClient<FileMon.FileMonInterface>(InChannelName);
            Interface.Ping();
        }
        unsafe public void Run(
            RemoteHooking.IContext InContext,
            String InChannelName)
        {
            // install hook...
            try
            {
                CreateFileHook = LocalHook.Create(
                    LocalHook.GetProcAddress("oci.dll", "OCIStmtFetch2"),
                    new DOCIStmtFetch2(DOCIStmtFetch2_Hooked),
                    this);
                CreateFileHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
            }
            catch (Exception ExtInfo)
            {
                Interface.ReportException(ExtInfo);
                return;
            }
            Interface.IsInstalled(RemoteHooking.GetCurrentProcessId());
            RemoteHooking.WakeUpProcess();
            // wait for host process termination...
            try
            {
                while (true)
                {
                    Thread.Sleep(500);
                    // transmit newly monitored file accesses...
                    if (Queue.Count > 0)
                    {
                        String[] Package = null;

                        lock (Queue)
                        {
                            Package = Queue.ToArray();

                            Queue.Clear();
                        }
                        Interface.OnOCIStmtFetch2(RemoteHooking.GetCurrentProcessId(), Package);
                    }
                    else
                        Interface.Ping();
                }
            }
            catch
            {
            }
        }

        [UnmanagedFunctionPointer(CallingConvention.StdCall,
            CharSet = CharSet.Ansi,
            SetLastError = true)]
        unsafe delegate int DOCIStmtFetch2(
            void* stmtp,
            void* errhp,
            UInt32 nrows,
            UInt16 orientation,
            UInt32 scroll,
            UInt32 mode);


        // just use a P-Invoke implementation to get native API access from C# (this step is not         necessary for C++.NET)
        [DllImport("oci.dll", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention =    CallingConvention.StdCall)]
       // [return: MarshalAs(UnmanagedType.I4)]
         unsafe static extern Int32 OCIStmtFetch2(
            void* stmtp,
            void* errhp,
            UInt32 nrows,
            UInt16 orientation,
            UInt32 scroll, 
            UInt32 mode);

        // this is where we are intercepting all file accesses!
        unsafe static Int32 DOCIStmtFetch2_Hooked(
            void* stmtp,
            void* errhp,
            UInt32 nrows,
            UInt16 orientation,
            UInt32 scroll, 
            UInt32 mode)
        {

            try
            {
                Main This = (Main)HookRuntimeInfo.Callback;
                    This.Queue.Push("[" + RemoteHooking.GetCurrentProcessId() + ":" +
                        RemoteHooking.GetCurrentThreadId() + "]: \"" + nrows + "\"");
            }
            catch (Exception ee)
            {
            }
            // call original API...
            int E = OCIStmtFetch2(
                  stmtp,
                  errhp,
                  nrows,
                  orientation,
                  scroll,
                  mode);

          return E;
        }
    }
}

如您所见,我将ub4映射为UInt32,ub2映射为UInt16,剑映射为Int32。第一次我使用IntPtr作为指针(两个第一个参数),但是代码不能正常工作。注入的dll截取函数调用完善,可以在原函数之前运行代码,可以调用原始函数并返回期望值,但当执行返回E时,目标应用程序会导致内存冲突异常并退出。正如您在代码中所看到的,然后我尝试使用void*指针和不安全关键字来启用在C#中使用指针,结果是相同的。与使用Detours的代码相比,我可以使用调试器检查的参数和指针值对于两个库都是相同的,因此类型映射看起来很好。不过,当我从DOCIStmtFetch2_Hooked返回时,代码会中断。

有人知道什么是不对的吗?即使我认为类型映射是可以的,我也将错误归咎于它们。

致以问候。

为了缩短源文件,我删除了锁部分。不管我是否锁定队列,问题仍然存在。

EN

回答 2

Stack Overflow用户

发布于 2013-06-27 02:54:15

甲骨文(oci.dll)使用"Cdecl“调用约定,您使用StdCall。尝试更改为"CallingConvention = CallingConvention.Cdecl“

票数 1
EN

Stack Overflow用户

发布于 2011-05-19 21:58:32

您忘了将This.Queue锁定在钩子中,但我不确定修复这个问题是否解决了您的问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6064702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档