سؤال

عندما يتم استضافة ActiveXObject في أداة نظام التشغيل Windows Desktop / Sidebar، فإن ActiveXoBject هو نوع من ملف التخزين المؤقت وملف DLL لأنه مغلق (مما يعني أنه لا يمكن نقله أو حذفه أو إعادة تسميته). المشكلة هي هذا؛ عند إغلاق الأداة بعد ذلك، لا يزال DLL مغلقا عبر الشريط الجانبي ويندوز ولا يمكن إزالته. يسبب هذا مشكلة كبيرة حيث لا يمكن تثبيت إصدار جديد من الأداة على الجزء العلوي من الإصدار السابق من الأداة، فقد فشل أثناء عملية حذفه دون أي رسائل خطأ.

هذا ليس سهل الاستخدام للغاية، لذا فأنا أبحث عن طريقة "تقطع" العلاقات إلى عنصر تحكم ActiveX بطريقة أو بأخرى خلال حدث تفريغ الأداة. آمل أن يخبرني شخص ما أن يقول لي ما إذا كان ذلك ممكنا أم لا، وإذا أعطاني بعض الأفكار حول كيفية تنفيذها.

FYI، أدوات Windows Sidebar هي في الواقع، فقط Windows Internet Explorer Server Windows، لذلك ربما يكون من الآمن افتراض أن أي أن السلوك نفسه.

تعديل: غير مقفلة يبدو أن تفعل الكثير مما أحتاج إليه، فكيف يمكنني تحقيق نفس الشيء برمجيا في .NET؟

هل كانت مفيدة؟

المحلول

حسنا، هذه مشكلة معقدة إلى حد ما. لقد رأيت هذا السلوك من قبل، أنا لست على دراية بأداة Windows Desktop / Sidebar لأنني لا أستخدمه. ومع ذلك تمكنت من التوصل إلى ثلاث طرق ممكنة للهجوم

1. مقبض من Technet.

لم يكن هذا فكرتي، هناك موضوع آخر stackoverflow التي توصي هذه الطريقة. ومع ذلك، أنا متشكك حول ما إذا كان هذا سيعمل أم لا. هناك فرق بين قفل الملفات (ما مقابض الأداة المساعدة هذه) وقفل "مكتبة محملة" وهو ما أفترضه هو المشكلة التي تواجهها مع ActiveX.

قمت بتعديل التعليمات البرمجية من هذا الموضوع قليلا، وهناك استخدامها.

public struct LockInfo
{
    public int PID;
    public string Handle;

    public LockInfo(int pid, string handle)
    {
        this.PID = pid;
        this.Handle = handle;
    }
}      

static List<LockInfo> getLockingInfo(string fileName)
{            
    List<LockInfo> lockingProcesses = new List<LockInfo>();

    Process tool = new Process();
    tool.StartInfo.FileName = "handle.exe";
    tool.StartInfo.Arguments = fileName;
    tool.StartInfo.UseShellExecute = false;
    tool.StartInfo.RedirectStandardOutput = true;
    tool.Start();
    tool.WaitForExit();
    string outputTool = tool.StandardOutput.ReadToEnd();

    // I;m not so hot with regex, so a bit of regex and a bit of manual splitting
    string matchPattern = @"(?<=\s+pid:\s+)\b(\d+)\b(\s+)\b(\S+:)";
    foreach (Match match in Regex.Matches(outputTool, matchPattern))
    {
        string[] temp = match.Value.Replace(":", "").Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        if (temp.Length == 2)
        {
            lockingProcesses.Add(new LockInfo(int.Parse(temp[0].Trim()), temp[1].Trim()));
        }
    }
    return lockingProcesses.Count > 0 ? lockingProcesses : null;
}

static bool closeFileHandle(List<LockInfo> lockingInfo)
{
    if ((lockingInfo == null) || (lockingInfo.Count == 0))
    {
        throw new ArgumentException("lockingProcesses cannot be null or empty");
    }

    bool fileClosed = true;

    foreach (LockInfo lockInfo in lockingInfo)
    {
        Process tool = new Process();
        tool.StartInfo.FileName = "handle.exe";
        tool.StartInfo.Arguments = string.Format("-c {0} -y -p {1}", lockInfo.Handle, lockInfo.PID.ToString());
        tool.StartInfo.UseShellExecute = false;
        tool.StartInfo.RedirectStandardOutput = true;
        tool.Start();
        tool.WaitForExit();
        string outputTool = tool.StandardOutput.ReadToEnd();
        if (outputTool.IndexOf("Handle closed") == -1)
        {
            fileClosed = false;
        }
    }
    return fileClosed;
}

public static void Main()
{            
    //Path to locked file, make sure the full path is in quotes
    string fileName = "\"" + @"C:\Your_Path\To_The\ActiveX.ocx" + "\"";
    List<LockInfo> lockInfo = getLockingInfo(fileName);
    if ((lockInfo != null) && (lockInfo.Count > 0))
    {
        closeFileHandle(lockInfo);
    }                                 
}

...


2. نمط Win32.

لا يوجد الكثير من المعلومات حول Internets حول هذا الأمر، ويبدو أن هناك بعض مكالمات API غير الموثقة اللازمة لسحب هذا بسلاسة.

أنا هذه الأمثلة C ++ قد تساعد.

لسوء الحظ، لم أستطع الحصول على هذا للعمل بسلاسة. لقد اختبرت هذه الطريقة باستخدام ActiveX محملة في MS Word. ثم حاولت فتح ActiveX، إنها ليست مستقرة للغاية وتسببت في كثير من الأحيان كلمة تحطمها. أعتقد أنه ليس لدي جروح حرب C ++ المطلوبة لتفكيك البرامج أعلاه بشكل صحيح.

جنبا إلى جنب مع هذا المثال من createremotethread في C # لقد وضعت هذا الرمز معا.

public struct ProcessInfo
{
    public Process Process;
    public ProcessModule Module;

    public ProcessInfo(Process process, ProcessModule module)
    {
        this.Process = process;
        this.Module = module;
    }
}

private static List<ProcessInfo> getProcessInfo(string fileName, bool partialMatch)
{
    List<ProcessInfo> myProcesses = new List<ProcessInfo>();

    Process[] runningProcesses = Process.GetProcesses();
    int i = 0;
    for (i = 0; i < runningProcesses.Length; i++)
    {
        Process currentProcess = runningProcesses[i];
        try
        {
            if (!currentProcess.HasExited)
            {
                try
                {
                    ProcessModuleCollection modules = currentProcess.Modules;
                    int j = 0;
                    for (j = 0; j < modules.Count; j++)
                    {
                        if (partialMatch)
                        {
                            if ((modules[j].FileName.ToLower().IndexOf(fileName.ToLower()) != -1))
                            {
                                myProcesses.Add(new ProcessInfo(currentProcess, modules[j]));
                                break;
                            }
                        }
                        else
                        {
                            if ((modules[j].FileName.ToLower().CompareTo(fileName.ToLower()) == 0))
                            {
                                myProcesses.Add(new ProcessInfo(currentProcess, modules[j]));
                                break;
                            }
                        }
                    }
                }
                catch (NotSupportedException)
                {
                    // You are attempting to access the Modules property for a process that is running on a remote computer. 
                    // This property is available only for processes that are running on the local computer. 
                }
                catch (InvalidOperationException)
                {
                    // The process Id is not available.
                }
                catch (Win32Exception)
                {
                    // You are attempting to access the Modules property for either the system process or the idle process. 
                    // These processes do not have modules.
                }
            }
        }
        catch (InvalidOperationException)
        {
            // There is no process associated with the object. 
        }
        catch (Win32Exception)
        {
            // The exit code for the process could not be retrieved. 
        }
        catch (NotSupportedException)
        {
            // You are trying to access the HasExited property for a process that is running on a remote computer.
            // This property is available only for processes that are running on the local computer.

        }
    }
    return myProcesses.Count > 0 ? myProcesses : null;
}

private static void forceRemoteCloseHandle(ProcessInfo processInfo)
{
    // Open remote process for write
    IntPtr hProcess = NativeMethods.OpenProcess(NativeMethods.PROCESS_CREATE_THREAD | NativeMethods.PROCESS_VM_OPERATION |
            NativeMethods.PROCESS_VM_WRITE | NativeMethods.PROCESS_VM_READ, false, processInfo.Process.Id);

    // Get the handle to CloseHandle in kernel32.dll
    IntPtr hKernel32 = NativeMethods.LoadLibrary("kernel32.dll");
    IntPtr hCloseHandle = NativeMethods.GetProcAddress(hKernel32, "CloseHandle");
    uint temp = 0;

    // Create the remote thread and point it to CloseHandle
    IntPtr hCreateRemoteThread = NativeMethods.CreateRemoteThread((IntPtr)hProcess, (IntPtr)0, 0, hCloseHandle, (IntPtr)processInfo.Module.BaseAddress, 0, out temp);

    // Wait for thread to end
    NativeMethods.WaitForSingleObject(hCreateRemoteThread, 2000);

    //Closes the remote thread handle
    NativeMethods.CloseHandle(hCreateRemoteThread);

    //Free up the kernel32.dll
    if (hKernel32 != null)
        NativeMethods.FreeLibrary(hKernel32);

    //Close the process handle
    NativeMethods.CloseHandle(hProcess);
}

private static void forceRemoteFreeLibrary(ProcessInfo processInfo)
{
    // Open remote process for write
    IntPtr hProcess = NativeMethods.OpenProcess(NativeMethods.PROCESS_CREATE_THREAD | NativeMethods.PROCESS_VM_OPERATION |
            NativeMethods.PROCESS_VM_WRITE | NativeMethods.PROCESS_VM_READ, false, processInfo.Process.Id);

    // Get the handle to FreeLibrary in kernel32.dll
    IntPtr hKernel32 = NativeMethods.LoadLibrary("kernel32.dll");
    IntPtr hFreeHandle = NativeMethods.GetProcAddress(hKernel32, "FreeLibrary");

    // Create the remote thread and point it to FreeLibrary
    uint temp = 0;
    IntPtr hCreateRemoteThread = NativeMethods.CreateRemoteThread((IntPtr)hProcess, (IntPtr)0, 0, hFreeHandle, (IntPtr)processInfo.Module.BaseAddress, 0, out temp);

    // Wait for thread to end
    NativeMethods.WaitForSingleObject(hCreateRemoteThread, 2000);

    //Closes the remote thread handle
    NativeMethods.CloseHandle(hCreateRemoteThread);

    //Free up the kernel32.dll
    if (hKernel32 != null)
        NativeMethods.FreeLibrary(hKernel32);

    // Close the process handle
    NativeMethods.CloseHandle(hProcess);        
}

public static void Main()
{
    string strFile = @"C:\Program Files\Microsoft Office\OFFICE11\MSCAL.OCX";
    List<ProcessInfo> lockingProcesses = getProcessInfo(strFile, false);

    foreach (ProcessInfo processInfo in lockingProcesses)
    {
        forceRemoteCloseHandle(processInfo);
        // OR
        forceRemoteFreeLibrary(processInfo);
    }

    // OR
    foreach (ProcessInfo procInfo in lockingProcesses)
    {
        procInfo.Process.Kill();
    }

}

internal static class NativeMethods
{
    internal const int PROCESS_TERMINATE = 0x0001;
    internal const int PROCESS_CREATE_THREAD = 0x0002;
    internal const int PROCESS_VM_OPERATION = 0x0008;
    internal const int PROCESS_VM_READ = 0x0010;
    internal const int PROCESS_VM_WRITE = 0x0020;

    internal const int PROCESS_QUERY_INFORMATION = 0x0400;

    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    internal static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
    internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    internal static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);

    [DllImport("kernel32", SetLastError = true)]
    internal static extern IntPtr LoadLibrary(string lpFileName);


    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern bool FreeLibrary(IntPtr hModule);

    [DllImport("kernel32")]
    public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);

    [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
    internal static extern int CloseHandle(IntPtr hPass);
}

...


3. مجرد استخدام غير مقفلة

هذه هي أفضل توصيتي. التعامل معها من Technet لا يمكن التعامل مع أقفال DLL / OCX المحملة (ضمن اختباراتي). Win32 هو فوضوي وغير موثق.

يوفر Unlocker الوصول إلى سطر الأوامر حتى تتمكن من الاتصال به بنفس طريقة التعامل معها بالضبط. فقط أحمق A /؟ بعد Unlocker.exe في موجه الأوامر لرؤية المفاتيح.

هنالك أيضا نسخة محمولة من غير مقفلة المتاحة حتى تتمكن من حلها في نشرك دون إجبار المستخدمين النهائيين على تثبيت التطبيق.

إذا فشل كل شيء آخر، فيمكنك الاتصال بمؤلف Unlocker، تحقق من هذا من README.

الترخيص

إذا كنت مهتما بإعادة توزيع إلغاء التوزيع، فما عليك إما في النموذج الأصلي أو المعدل، أو ترغب في استخدام التعليمات البرمجية المصدرية لإلغاء الافراج في منتج، فيرجى إرسال بريد إلكتروني إلى ccollomb@yahoo.com مع تفاصيل.

...


4. استخدام المعالجة المكتبات المشتركة المكتبات

اكتشفت للتو هذه الأداة الرائعة: عملية القراصنة العملية وهو مكتوب في رمز C # 100٪ (على الرغم من أنه يستخدم الكثير من وظائف Winapi عبر P / Invoke تحت غطاء محرك السيارة).

أفضل شيء في هذا: إنه مصدر مفتوح (LGPL'd) ويوفر مكتبتين يمكن للمطورين الرجوع إليه في حلولهم: processhacker.common processhacker.native.

قمت بتنزيل المصدر وكلمة تحذير فقط، إنه حل كبير جدا، لذلك قد يستغرق الأمر بعض الوقت لمعرفة ما / كيفية استخدامه بالضبط.

يستخدم وظائف API غير الموثقة (NTDLL.DL) تحدثت عنه في الخيار 2 ويمكن أن تفعل كل ما يمكن فتحه وكل شيء أكثر بكثير.

نصائح أخرى

لست متأكدا مما إذا كان هذا يعمل من أجل كائنات ActiveX ولكنه بالتأكيد لا يقوم بالتجميع بتجميعات .NET. يمكنني استخدامه ليتم التخلص منه حيث يجب الكتابة فوق DLL بسلاسة. الآلية المستخدمة هي نسخ الظل.

يبدو مقابض إغلاق من خارج التطبيق لا يوجد خيار آمن للغاية.

ليس الحل ربما فكرة أو اتجاه ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top