문제

나는 우리의 내부 사람들이 더 이상 사용해서는 안되는 오래된 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 응용 프로그램을 생성 및 종료 할 수 있습니다.

도움이되기를 바랍니다 ...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top