ATL COM dll 中的缓冲区溢出

Posted

技术标签:

【中文标题】ATL COM dll 中的缓冲区溢出【英文标题】:Buffer overrun in ATL COM dll 【发布时间】:2012-03-09 02:19:47 【问题描述】:

我正在尝试使用与我最初在 C# 中使用的另一个匹配的 ATL 创建一个 COM dll。此 dll 通常由我没有源代码的第三方 dll 调用,因此我希望 UUID 与 progID 相同。我还有一个测试应用程序,它调用我的 dll 中的方法,这就是我测试它的方式。测试应用定义的接口是:

STDMETHOD(GetSwitchCriteria)(double* intensity, double* minMass, double* maxMass, 
    BOOL* selectIntensity, long* numOfDepCycles) = 0;
STDMETHOD(GetChargeStateParam)(short* minCharge, short* maxCharge, BOOL* doChargeState) = 0;
STDMETHOD(GetInclusionList)(double* intensity, double* theList, short* numOfItems) = 0;
STDMETHOD(GetExclusionList)(long* exRTWindow, double* theMassList, long* theRTList, 
    short* numOfItems) = 0;
STDMETHOD(GetOtherCriteria)(long* smartFilterTime, double* isoExclusionWin,
    double* massTolerance, BOOL* isPPM) = 0;
STDMETHOD(GetIsotopeMatchParam)(double* theMassList, double* theAbundanceList,
    short* numOfItems, double* abTolerance, double* maTolerance) = 0;

// called at the start of each IDA run
STDMETHOD(OnInitIDA)() = 0;
// called at the end of each survey scan
STDMETHOD(OnScreenSurveySpec)() = 0;
// called at the time of switch
STDMETHOD(OnPrepareNextScan)(double* selectedMasses, double* selectedIntensities, long* selectedCharges, int itemCount) = 0;

在我使用 ATL 的新 dll 中,我试图模仿这一点,定义如下:

STDMETHOD(GetSwitchCriteria)(DOUBLE* intensity, DOUBLE* minMass, DOUBLE* maxMass, VARIANT_BOOL* selectIntensity, LONG* numOfDepCycles);
STDMETHOD(GetChargeStateParam)(SHORT* minCharge, SHORT* maxCharge, VARIANT_BOOL* doChargeState);
STDMETHOD(GetInclusionList)(DOUBLE* intensity, DOUBLE* theList, SHORT* numOfItems);
STDMETHOD(GetExclusionList)(LONG* exRTWindow, DOUBLE* theMassList, LONG* theRTList, SHORT* numOfItems);
STDMETHOD(GetOtherCriteria)(LONG* smartFilterTime, DOUBLE* isoExclusionWin, DOUBLE* massTolerance, VARIANT_BOOL* isPPM);
STDMETHOD(GetIsotopeMatchParam)(DOUBLE* theMassList, DOUBLE* theAbundanceList, DOUBLE* abTolerance, DOUBLE* maTolerance);
STDMETHOD(OnInitIDA)(void);
STDMETHOD(OnScreenSurveySpec)(void);
STDMETHOD(OnPrepareNextScan)(DOUBLE* selectedMasses, DOUBLE* selectedIntensities, LONG* selectedCharges, LONG itemCount);

最初我对一些参数使用了 BOOL,但是当我在 TLB 文件中查找它时,我注意到 C# dll 使用了 VARIANT_BOOL。

当我调用两个没有参数的方法时,我得到的 HRESULT 为 0。对于 OnPrepareNextScan 方法也是如此。但是,当我打电话给其他人时,我得到一个异常,缓冲区溢出,我不确定为什么会这样。有谁知道为什么会发生这种情况或我该如何调查?

这是否可能是由于两个接口中定义的类型之间的类型不兼容,以及我在创建用于方法的变量时使用的类型之间的类型不兼容?用于调用其中一种方法的代码示例如下:

short minCharge = 0;
short maxCharge = 0;
BOOL doChargeState = FALSE;

result = m_pUserIDA->GetChargeStateParam(&minCharge, &maxCharge, &doChargeState);
    std::cout << "HRESULT of GetChargeStateParam: " << result << std::endl;

尝试了下面提到的 LONGLONG 解决方案,但似乎没有帮助。

我认为我应该从 C# dll 发布原始界面。

[Guid("76F452FF-7A89-11d4-8A2C-00B0D023C6A0")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public unsafe interface IUserIDA

    [DispId(1)]
    void GetSwitchCriteria(ref double intensity, ref double minMass, ref double maxMass, ref bool selectIntensity, ref long numOfDepCycles);

    [DispId(2)]
    void GetChargeStateParam(ref short minCharge, ref short maxCharge, ref bool doChargeState);

    [DispId(3)]
    void GetInclusionList(ref double intensity, ref double theList, ref short numOfItems);

    [DispId(4)]
    void GetExclusionList(ref long exRTWindow, ref double theMassList, ref long theRTList, ref short numOfItems);

    [DispId(5)]
    void GetOtherCriteria(ref long smartFilterTime, ref double isoExclusionWin, ref double massTolerance, ref bool isPPM);

    [DispId(6)]
    void GetIsotopeMatchParam(ref double theMassList, ref double theAbundanceList, ref short numOfItems, ref  double abTolerance, ref double maTolerance);

    [DispId(7)]
    void OnInitIDA();

    [DispId(8)]
    void OnScreenSurveySpec();

    [DispId(9)]
    void OnPrepareNextScan(double* selectedMasses, double* SelectedIntensities, long* selectedCharges, int itemCount);

最后一种方法,OnPrepareNextScan 是唯一一个似乎有效的方法,您可以看到它是使用普通指针而不是 .NET ref 语句定义的,这可能是个问题吗?

我想我可能还包括每个类型的类型库文件,也许这些文件的不同会清楚问题是什么以及两者之间的任何差异:

原始 C# dll:

// Generated .IDL file (by the OLE/COM Object Viewer)
// 
// typelib filename: AnalystIDA.dll

[
 uuid(7ED40FB0-D178-47FA-9EF3-B434E0803D5F),
 version(1.0),
 custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, "Analyst_UserIDA, Version=1.0.0.0,     Culture=neutral, PublicKeyToken=de4cf4f15e545467")

]
library Analyst_UserIDA

// TLib :     // TLib : mscorlib.dll : BED7F4EA-1A96-11D2-8F08-00A0C9A6186D
importlib("mscorlib.tlb");
// TLib : OLE Automation : 00020430-0000-0000-C000-000000000046
importlib("stdole2.tlb");

// Forward declare all types defined in this typelib
interface IUserIDA;
interface _Utility;

[
  uuid(CDD947DD-7B9E-382E-9F6F-55218F927C3A),
  version(1.0),
  custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Analyst_UserIDA.Utility")
]
coclass Utility 
    [default] interface _Utility;
    interface _Object;
;

[
  odl,
  uuid(76F452FF-7A89-11D4-8A2C-00B0D023C6A0),
  version(1.0),
  oleautomation,
  custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Analyst_UserIDA.IUserIDA")    

]
interface IUserIDA : IUnknown 
    HRESULT _stdcall GetSwitchCriteria(
                    [in, out] double* intensity, 
                    [in, out] double* minMass, 
                    [in, out] double* maxMass, 
                    [in, out] VARIANT_BOOL* selectIntensity, 
                    [in, out] int64* numOfDepCycles);
    HRESULT _stdcall GetChargeStateParam(
                    [in, out] short* minCharge, 
                    [in, out] short* maxCharge, 
                    [in, out] VARIANT_BOOL* doChargeState);
    HRESULT _stdcall GetInclusionList(
                    [in, out] double* intensity, 
                    [in, out] double* theList, 
                    [in, out] short* numOfItems);
    HRESULT _stdcall GetExclusionList(
                    [in, out] int64* exRTWindow, 
                    [in, out] double* theMassList, 
                    [in, out] int64* theRTList, 
                    [in, out] short* numOfItems);
    HRESULT _stdcall GetOtherCriteria(
                    [in, out] int64* smartFilterTime, 
                    [in, out] double* isoExclusionWin, 
                    [in, out] double* massTolerance, 
                    [in, out] VARIANT_BOOL* isPPM);
    HRESULT _stdcall GetIsotopeMatchParam(
                    [in, out] double* theMassList, 
                    [in, out] double* theAbundanceList, 
                    [in, out] short* numOfItems, 
                    [in, out] double* abTolerance, 
                    [in, out] double* maTolerance);
    HRESULT _stdcall OnInitIDA();
    HRESULT _stdcall OnScreenSurveySpec();
    HRESULT _stdcall OnPrepareNextScan(
                    [in, out] double* selectedMasses, 
                    [in, out] double* SelectedIntensities, 
                    [in, out] int64* selectedCharges, 
                    [in] long itemCount);
;

[
  uuid(5B2DBDD4-B763-428A-B48F-2E148138E7A4),
  version(1.0),
  custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Analyst_UserIDA.UserIDAObject")
]
coclass UserIDAObject 
    interface _Object;
    [default] interface IUserIDA;
;

[
  odl,
  uuid(8094073C-362D-37BB-9791-E9D163271C73),
  hidden,
  dual,
  oleautomation,
  custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Analyst_UserIDA.Utility")    

]
interface _Utility : IDispatch 
;
;

我的新 dll:

// Generated .IDL file (by the OLE/COM Object Viewer)
// 
// typelib filename: AnalystIDA.dll

[
 uuid(7ED40FB0-D178-47FA-9EF3-B434E0803D5F),
 version(1.0),
 helpstring("AnalystIDA 1.0 Type Library"),
 custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 117441012),
 custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1329510523),
 custom(DE77BA65-517C-11D1-A2DA-0000F8773CE9, "Created by MIDL version 7.00.0500 at  Fri     Feb 17 15:28:38 2012
")

]
library AnalystIDALib

// TLib :     // TLib : OLE Automation : 00020430-0000-0000-C000-000000000046
importlib("stdole2.tlb");

// Forward declare all types defined in this typelib
interface IUserIDA;

[
  uuid(5B2DBDD4-B763-428A-B48F-2E148138E7A4),
  helpstring("UserIDAObject Class")
]
coclass UserIDAObject 
    [default] interface IUserIDA;
;

[
  odl,
  uuid(76F452FF-7A89-11D4-8A2C-00B0D023C6A0),
  helpstring("IUserIDA Interface"),
  dual,
  nonextensible,
  oleautomation
]
interface IUserIDA : IDispatch 
    [id(0x00000001), helpstring("method GetSwitchCriteria")]
    HRESULT GetSwitchCriteria(
                    [in, out] double* intensity, 
                    [in, out] double* minMass, 
                    [in, out] double* maxMass, 
                    [in, out] VARIANT_BOOL* selectIntensity, 
                    [in, out] long* numOfDepCycles);
    [id(0x00000002), helpstring("method GetChargeStateParam")]
    HRESULT GetChargeStateParam(
                    [in, out] short* minCharge, 
                    [in, out] short* maxCharge, 
                    [in, out] VARIANT_BOOL* doChargeState);
    [id(0x00000003), helpstring("method GetInclusionList")]
    HRESULT GetInclusionList(
                    [in, out] double* intensity, 
                    [in, out] double* theList, 
                    [in, out] short* numOfItems);
    [id(0x00000004), helpstring("method GetExclusionList")]
    HRESULT GetExclusionList(
                    [in, out] long* exRTWindow, 
                    [in, out] double* theMassList, 
                    [in, out] long* theRTList, 
                    [in, out] short* numOfItems);
    [id(0x00000005), helpstring("method GetOtherCriteria")]
    HRESULT GetOtherCriteria(
                    [in, out] long* smartFilterTime, 
                    [in, out] double* isoExclusionWin, 
                    [in, out] double* massTolerance, 
                    [in, out] VARIANT_BOOL* isPPM);
    [id(0x00000006), helpstring("method GetIsotopeMatchParam")]
    HRESULT GetIsotopeMatchParam(
                    [in, out] double* theMassList, 
                    [in, out] double* theAbundanceList, 
                    [in, out] double* abTolerance, 
                    [in, out] double* maTolerance);
    [id(0x00000007), helpstring("method OnInitIDA")]
    HRESULT OnInitIDA();
    [id(0x00000008), helpstring("method OnScreenSurveySpec")]
    HRESULT OnScreenSurveySpec();
    [id(0x00000009), helpstring("method OnPrepareNextScan")]
    HRESULT OnPrepareNextScan(
                    [in, out] double* selectedMasses, 
                    [in, out] double* selectedIntensities, 
                    [in, out] long* selectedCharges, 
                    [in] long itemCount);
;
;

另一个编辑: 我注意到 ProgID Analyst_UserIDA.UserIDAObject 没有出现在我的新 dll 的类型库中。这用于在测试应用程序中创建 UserIDAObject 的实例: IUserIDAPtr m_pUserIDA; ::CoInitialize(m_pUserIDA); m_pUserIDA.CreateInstance(_T("Analyst_UserIDA.UserIDAObject"));

更多进展/困惑: 我决定通过创建一个调用此 dll 的 C# 项目来查看 DLL 是否存在问题。当我这样做时,我遇到了工作问题。我还注意到最初看起来有效的方法并没有。我向其中一个添加了一个 sleep 语句,当我的测试应用程序调用它时,它似乎永远不会被执行。

【问题讨论】:

【参考方案1】:

请注意,在 Win32 中 LONG 是 32 位整数,而在 C# 中 long 是 64 位整数。这可能会导致您描述的问题。

解决方案是在 C# 使用 long 时使用 __int64LONGLONG

【讨论】:

我会试一试的。我正在查找这个,但我发现了相当不一致的答案并且有点困惑。

以上是关于ATL COM dll 中的缓冲区溢出的主要内容,如果未能解决你的问题,请参考以下文章

缓冲区溢出(vs)缓冲区溢出(vs)堆栈溢出[重复]

缓冲区溢出

Microsoft Windows 智能卡认证缓冲区溢出漏洞 (CVE-2017-0176)

这个 C 代码中的缓冲区溢出漏洞在哪里?

Adobe Reader 缓冲区溢出漏洞 (CVE-2010-2883)漏洞分析报告

多图详解缓冲区溢出问题