문제
나는 우리의 내부 사람들이 더 이상 사용해서는 안되는 오래된 16 비트 응용 프로그램의 실행을 위해 갇히고 있습니다. 그들은 1985 년 DOS 앱이므로 덫을 놓으십시오. ntvdm.exe에 따라 시작되는 모든 프로세스를 캡처합니다.
이제 문제는 NTVDM이 실제로 실행중인 프로그램을 찾는 것입니다. 분명히 1985 년 프로그램에는 실행할 수 있어야하는 커플이 있으므로 NTVDM에 숨어있는 실제 EXE 이름을 봐야합니다.
WqlEventQuery query =
new WqlEventQuery("__InstanceCreationEvent",
new TimeSpan(0, 0, 1),
"TargetInstance isa \"Win32_Process\"");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Start();
...
static void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
ProcessInfo PI = new ProcessInfo();
PI.ProcessID = int.Parse(instance["ProcessID"].ToString());
PI.ProcessName = instance["Name"].ToString();
PI.ProcessPath = instance["ExecutablePath"].ToString();
// Here's the part I need...
PI.ActualEXE = ???;
// ... do the magic on the PI class ...
instance.Dispose();
}
인스턴스 정보를 캡처하면 명령 줄을 얻을 수 있지만 인수는 "-f -i10"입니다 ... 명령 줄에 exe 이름이 없습니다. 실제로 실행중인 16 비트 응용 프로그램의 EXE 이름을 결정하기 위해보고있는 다른 방법/속성이 있습니까?
업데이트: 질문을 개선하겠습니다. NTVDM 프로세스를 찾을 수 있다면, 아래에서 실행되는 EXE의 실제 경로를 프로그래밍 방식으로 어떻게 알 수 있습니까?
감사.
해결책
트릭은 사용하지 않는 것입니다 vdmenumprocesswow (VDMS를 제공하는) 그러나 사용합니다. vdmenumtaskswow. 이 기능으로 전달하는 열거 기능은 지정된 VDM의 각 16 비트 작업마다 호출됩니다.
나는 그것을 직접 확인하지 않았지만 문서에 따르면 CodeProject의 라이브러리 Proc16 열거 값을 통과하면 정확히 그렇게합니다. C ++입니다. 해당 코드를 컴파일하고 C#에서 호출하는 데 도움이 필요한 경우 알려 주시면 예를 들어 보겠습니다.
이 기술을 사용하는 프로그램은 다음과 같습니다 프로세스 마스터, 그것은 전체 소스와 함께 제공됩니다. 필요한 정보를 제공하는지 확인하기 위해 실행하는 것이 좋습니다. 그렇다면이 메소드가 자신의 응용 프로그램에 적용 할 수 있습니다 (Windows Vista 또는 7에서 실행되지 않으면 이전 VB5 코드를 사용하지 않습니다. 호환됩니다. XP에서 실행해야합니다).
이러한 기능이있는 것들이 계획대로 진행되지 않으면 Vista에있을 수 있으며 이것에 설명 된 핫픽스가 필요할 수 있습니다. stackoverflow 질문, 그것은 가리킨다 핫픽스 다운로드, 차례로 여기에 설명되어 있습니다:
"vdmenumprocesswow 함수를 사용하여 가상 DOS 머신을 열거하는 응용 프로그램은 32 비트 버전의 Windows Vista를 실행중인 컴퓨터에서 출력 또는 잘못된 출력을 반환합니다."
업데이트: 이것이 유망한 것처럼 보이지만 패치를 적용하고 Microsoft를 포함하여 여러 버전의 코드를 실행했으며 모두 XP에서 작동하지만 Vista에서 조용히 실패 (오류 또는 잘못된 반환 값).
"Kinda"작업 코드
업데이트: C#에서 잘 컴파일하는 다음 코드를 사용하여 (다른 것들 중에서도) 실험했습니다 (더 간단하게 작성할 수 있지만 마샬-메이킹 위험을 실행하고 싶지는 않았습니다). 이 기능을 추가하면 호출 할 수 있습니다 Enum16BitProcesses
, 16 비트 프로세스의 EXE 파일의 파일 이름을 콘솔에 작성합니다.
Vista 32 비트에서 실행할 수 없습니다. 그러나 아마도 다른 사람들은 그것을 시도하고 컴파일하거나 코드에서 오류를 찾을 수 있습니다. 다른 시스템에서 작동하는지 아는 것이 좋을 것입니다.
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
}
}
업데이트: 흥미로운 읽기 유명한 Matt Pietrek. 끝까지 어딘가에 문장을 염두에 두십시오.
"우선, MS-DOS 기반 프로그램은 항상 별도의 NTVDM 세션에서 실행되는 것 같습니다. 16 비트 Windows 기반 프로그램과 같은 세션에서 MS-DOS 기반 프로그램을 실행할 수 없었습니다. 동일한 NTVDM 세션에서 독립적으로 시작된 MS-DOS 기반 프로그램을 실행할 수 있습니다. 실제로 MS-DOS 프로그램을 실행하는 NTVDM 세션은 vdmenumprocesswow 열거에 나타나지 않습니다. "
어떤 프로세스가로드되었는지 확인하려면 NTVDM에 후크를 작성하거나 파일에 대한 액세스를 모니터링하는 리스너를 작성해야합니다. 특정 DOS 파일을 읽으려고하는 응용 프로그램이 ntvdm.exe이면 Bingo입니다. ntvdm.exe에만 첨부 된 DLL을 작성하고 싶을 수도 있지만 이제 우리는 우리 자신보다 조금 앞서 나가고 있습니다. 짧은 이야기 : NTVDM으로 의이 작은 타는 것은 결국 실제 사기처럼 보이는 "가능성"을 보여주었습니다.
다른 방법이 있지만 시간이 너무 짧아 예제를 만들 수 있습니다. DOS 메모리 세그먼트에서 주위를 찌를 수 있으며 EXE는 일반적으로 동일한 세그먼트에로드됩니다. 그러나 그것이 결국 같은 결과와 그것이 노력할 가치가 있는지 여부는 확실하지 않습니다.
다른 팁
이것은 나를 위해 작동합니다 :
지침을 따르십시오 Windows XP의 소프트웨어 제한 정책에 대한 설명 로컬 또는 도메인 정책 편집기를 열려면
소프트웨어 제한 정책에 따라 -> 추가 규칙에 따라 마우스 오른쪽 버튼을 클릭하고 새 해시 규칙을 선택하십시오.
찾아보기 (예를 들어)
edit.com
. 보안 수준이 허용되지 않도록 설정되어 있는지 확인하십시오. 확인을 클릭하십시오.
지금,
C:\>edit
The system cannot execute the specified program.
(나는 같은 결과를 얻습니다 command.com
그리고 cmd.exe
- win xp 아래)
에서 VDMDBG 기능에 대한이 링크, "vdmenumprocesswow ()"를 호출 할 수 있습니다. PSAPI를 사용하여 프로세스 내에서 모듈을 열거합니다.
16 비트 DOS 애플리케이션에 관한 참고 사항 :
VDMDBG 기능 중 어느 것도 16 비트 DOS 애플리케이션에서 작동하지 않습니다. DOS VDMS를 열거하려면 다른 방법을 사용해야합니다. 먼저 vdmenumprocesswow ()를 사용하여 모든 Win16 VDM의 목록을 작성한 다음 다른 체계 (예 : PSAPI)를 사용하여 NTVDM.EXE의 모든 인스턴스를 열거 할 수 있습니다. Win16 목록에 있지 않은 전체 열거의 NTVDM.Exe는 DOS VDM입니다. CreateProcess () 및 TerminateProcess ()를 사용하여 16 비트 DOS 응용 프로그램을 생성 및 종료 할 수 있습니다.
도움이되기를 바랍니다 ...