我正在捕获一些旧的16位应用程序的执行,我们的内部人员不应该再使用。它们是1985年的DOS应用程序,所以捕获它们很容易…捕获在ntvdm.exe下启动的任何进程
现在,问题是找出哪个程序ntvdm实际上是在幕后运行的。显然有一对1985年的程序应该被允许运行,所以我需要查看隐藏在ntvdm下的实际exe名称。ojit_pre
当我捕获实例信息时,我可以获得命令行,但参数是“-f-i10”…命令行上没有exe名称。有没有其他方法/属性可以帮助我确定实际运行的16位应用程序的exe名称?
更新:让我完善一下这个问题:如果我能找到ntvdm进程,我如何——以编程的方式——知道下面正在执行的exe的实际路径?
谢谢。
最佳答案
诀窍不是使用VDMEnumProcessWOW(它提供vdms),而是使用VDMEnumTasksWOW。将为指定VDM中的每个16位任务调用传递给此函数的枚举器函数。
我自己没有检查过,但是根据文档,如果您传入proc16 enum值,那么这个library of CodeProject就可以做到这一点。它是C++,如果你需要帮助编译这个代码并从C调用它,请让我知道,我给你举个例子。
使用此技术的程序是Process Master,它带有完整的源代码。我建议您运行它来确定它是否提供了您需要的信息,如果是,您可以将此方法应用于您自己的应用程序(它不在WindowsVista或7上运行,它使用旧的VB5代码,显然它不兼容)。它应该在xp上运行)。
如果这些功能没有按计划进行,您可能在vista上,可能需要本StackOverflow question中所述的修补程序,该修补程序指向downloading a hotfix,而这又是described here:
“使用
vdmenumprocesswow函数到
枚举虚拟DOS计算机返回
上没有输出或输出不正确
运行32位的计算机
Windows Vista版本”
更新:虽然这看起来很有希望,但我应用了补丁,运行了包括微软在内的多个版本的代码,虽然它们都在xp上工作,但在vista上它们会无声地失败(没有错误,或者错误的返回值)。
“类似”的工作代码
更新:我(和其他人一起)尝试了以下代码,这些代码在c中编译得很好(可以编写得更简单,但我不想冒封送处理错误的风险)。添加这些函数时,可以调用Enum16BitProcesses
,它会将16位进程的exe文件的文件名写入控制台。
我不能在32位vista上运行它。但也许其他人可以尝试编译它,或者在代码中找到错误。很高兴知道它是否适用于其他系统:
public class YourEnumerateClass
{
public static void Enum16BitProcesses()
{
// create a delegate for the callback function
ProcessTasksExDelegate procTasksDlgt =
new ProcessTasksExDelegate(YourEnumerateClass.ProcessTasksEx);
// this part is the easy way of getting NTVDM procs
foreach (var ntvdm in Process.GetProcessesByName("ntvdm"))
{
Console.WriteLine("ntvdm id = {0}", ntvdm.Id);
int apiRet = VDMEnumTaskWOWEx(ntvdm.Id, procTasksDlgt, IntPtr.Zero);
Console.WriteLine("EnumTaskWOW returns {0}", apiRet);
}
}
// declaration of API function callback
public delegate bool ProcessTasksExDelegate(
int ThreadId,
IntPtr hMod16,
IntPtr hTask16,
IntPtr ptrModName,
IntPtr ptrFileName,
IntPtr UserDefined
);
// the actual function that fails on Vista so far
[DllImport("VdmDbg.dll", SetLastError = false, CharSet = CharSet.Auto)]
public static extern int VDMEnumTaskWOWEx(
int processId,
ProcessTasksExDelegate TaskEnumProc,
IntPtr lparam);
// the actual callback function, on Vista never gets called
public static bool ProcessTasksEx(
int ThreadId,
IntPtr hMod16,
IntPtr hTask16,
IntPtr ptrModName,
IntPtr ptrFileName,
IntPtr UserDefined
)
{
// using PtrToStringAnsi, based on Matt's comment, if it fails, try PtrToStringAuto
string filename = Marshal.PtrToStringAnsi(ptrFileName);
Console.WriteLine("Filename of WOW16 process: {0}", filename);
return false; // false continues enumeration
}
}
最新消息:马特·皮特瑞克。记住这句话,在接近结尾的地方:
“首先,基于ms-dos的程序
似乎总是在单独的ntvdm中运行
会议。我从来没能得到
运行在
与基于16位Windows的会话相同
程序。我也拿不到两个
独立启动基于ms-dos
要在同一ntvdm中运行的程序
会话。实际上,ntvdm会话
运行MS-DOS程序不会出现
在vdmenumprocesswow枚举中。“
似乎,要了解加载了哪些进程,您需要将一个钩子写入ntvdm或编写一个侦听器来监视对该文件的访问。当试图读取某个dos文件的应用程序是ntvdm.exe时,它就是bingo。您可能想编写一个只附加到ntvdm.exe的dll,但现在我们有点超前了。长话短说:这次进入NTVDM的小旅行显示了“可能性”,最终出现了真正的骗局。
还有一种方法,但时间太短,无法树立榜样。您可以在DOS内存段中插入,EXE通常加载在同一段中。但我不确定这是否最终会导致同样的结果,也不确定这是否值得努力。