切断。净COM互操作会从其宿主进程
-
18-09-2019 - |
题
当一个ActiveXObject是举办的Windows桌面/栏的小工具,ActiveXObject是种缓和的DLL文件为它被锁定(这意味着它不能移动,删除或重新命名).问题是这样;当小工具随后关闭,DLL仍然是锁着的窗栏而不被删除。这会导致一个重大问题由此使一个新版本的工具,不能安装在顶部的一个早期版本的工具,它将失败的过程中删除,它没有任何错误信息。
这并不是非常友好的用户,所以我在寻找一种"切割"的联系件以某种方式控制在小工具卸载活动。我希望有人能告诉我这是否是可能的,如果它是给我一些想法,如何实现它。
仅供参考,窗栏的小工具是实际上只是Internet Explorer windows服务器,所以它可能是安全的假设即表现出相同行为。
编辑: 解锁 似乎做什么,我需要做的,所以我怎么可以实现同样的事情编程方式。净?
解决方案
好吧这是一个相当复杂的问题。我已经看到这种行为之前,我不熟悉Windows桌面/栏的小工具,因为我不要使用它。不过我设法拿出三种可能的方法的攻击
1. 手柄 从TechNet
这不是我的主意, 还有另一个计算器螺纹 建议这种方法。但我怀疑是否这将工作。之间是有区别的文件锁(什么这个工具处理)和"装入库"锁定它是什么,我的假设是问题你有件.
我修改了代码线略,他们使用的过程。杀()释放锁,我将认为这是更好的使用handle.exe 释放锁。
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风格
没有了很多信息在互联网络上有关此,这似乎有一些无证件的api调,需要把这顺利。
我这c++的例子可能会有帮助。
不幸的是,我不能让这个无缝工作。我已经测试了这种方法使用一个插件载MS Word.然后我试着解开件,它不是很稳定和常常导致词崩溃。我想我没有必要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/也门锁(根据我的测试).Win32是混乱和无证。
解锁了命令行访问,所以你可以叫它在完全相同的方式handle.exe.只是怪人a/?后unlocker.exe 在一个命令来看看的开关。
还有一个 便携版本的提供解锁 所以你可以捆绑它入您的部署没有强制终端用户安装应用程序。
如果一切都失败了,你可以联系的作者解锁,检查了此从他的自述。
许可
如果你有兴趣 重新分配是解锁无论是在 原来或修改形式,或希望 使用解锁源代码产品, 请发送电子邮件 ccollomb@yahoo.com 与的详细信息。
...
4.使用过程中的黑客的共享图书馆
我刚刚发现这个辉煌的工具: 进程的黑客 这是写在100%C#代码(虽然它并使用了大量的WinAPI职能通过P/援引擎盖下).
关于这一点的最好的事情:它的open source(LGPL会)和提供了两个库的开发人员可以参考在他们的方案:ProcessHacker.共同ProcessHacker.本地人。
我下载源并只是一个词警告,它是一个相当大的解决方案,因此可能需要一点时间来弄清楚到底什么如何来使用它。
它使用无证API functions(ntdll.dl)我谈到在备选方案2和可以做的一切是解锁可以和一个整体很多。
其他提示
不知道这是否适用于ActiveX对象,但它确实明确为.NET程序集。我用它的单元测试,其中DLL都要顺利覆盖。使用的机制是影子复制。
关闭来自外部的应用程序似乎不是一个真正的非常安全的选择处理。
它不是溶液也许一个想法或方向...