2013-04-19 16 views
5

Sto cercando di ottenere la directory di lavoro corrente del processo selezionato. Sono sicuro che sia possibile, perché strumenti come Process Explorer possono mostrare queste informazioni. Ho scoperto che questa informazione è memorizzata in PEB.Leggi l'altra directory corrente di processo in C#

Inoltre ho trovato il post del blog Oleksiy: http://eazfuscator.blogspot.com/2011/06/reading-environment-variables-from.html, ma tutte le mie modifiche sono totalmente a meno che.

Quindi la mia domanda è: come posso leggere queste informazioni in C#? Se il codice Oleksiy è un buon modo, come dovrei modificare il suo codice per ottenere queste informazioni?

+3

Questo non è qualcosa che le app dovrebbero fare l'un l'altro. L'unico uso valido sarebbe uno strumento diagnostico di sorta. –

+0

Hai ragione, ho bisogno di questo per il dipartimento di sicurezza –

+0

Intendi il dipartimento di insicurezza? –

risposta

7

Come altri hanno sottolineato, questo è completamente non documentato, ma qui è un pezzo di codice che lo fa (ad oggi sembra funzionare). Ovviamente, deve essere eseguito come amministratore. Si noti che può funzionare per qualsiasi bitness di processo, a 32 o 64 bit (alcuni process possono segnalare un accesso negato, anche in esecuzione come amministratore), con qualsiasi destinazione di compilazione (x86 o x64). È anche in grado di leggere la riga di comando. Utilizzare a proprio rischio!

// All offset values below have been tested on Windows 7 & 8 only 
// but you can use WinDbg "dt ntdll!_PEB" command and search for ProcessParameters offset to find the truth, depending on the OS version 
public static class ProcessUtilities 
{ 
    public static string GetCurrentDirectory(int processId) 
    { 
     return GetProcessParametersString(processId, Environment.Is64BitOperatingSystem ? 0x38 : 0x24); 
    } 

    public static string GetCurrentDirectory(this Process process) 
    { 
     if (process == null) 
      throw new ArgumentNullException("process"); 

     return GetCurrentDirectory(process.Id); 
    } 

    public static string GetCommandLine(int processId) 
    { 
     return GetProcessParametersString(processId, Environment.Is64BitOperatingSystem ? 0x70 : 0x40); 
    } 

    public static string GetCommandLine(this Process process) 
    { 
     if (process == null) 
      throw new ArgumentNullException("process"); 

     return GetCommandLine(process.Id); 
    } 

    private static string GetProcessParametersString(int processId, int offset) 
    { 
     IntPtr handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId); 
     if (handle == IntPtr.Zero) 
      throw new Win32Exception(Marshal.GetLastWin32Error()); 

     int processParametersOffset = Environment.Is64BitOperatingSystem ? 0x20 : 0x10; 
     try 
     { 
      if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess) // are we running in WOW? 
      { 
       PROCESS_BASIC_INFORMATION_WOW64 pbi = new PROCESS_BASIC_INFORMATION_WOW64(); 
       int hr = NtWow64QueryInformationProcess64(handle, 0, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); 
       if (hr != 0) 
        throw new Win32Exception(hr); 

       long pp = 0; 
       hr = NtWow64ReadVirtualMemory64(handle, pbi.PebBaseAddress + processParametersOffset, ref pp, Marshal.SizeOf(pp), IntPtr.Zero); 
       if (hr != 0) 
        throw new Win32Exception(hr); 

       UNICODE_STRING_WOW64 us = new UNICODE_STRING_WOW64(); 
       hr = NtWow64ReadVirtualMemory64(handle, pp + offset, ref us, Marshal.SizeOf(us), IntPtr.Zero); 
       if (hr != 0) 
        throw new Win32Exception(hr); 

       if ((us.Buffer == 0) || (us.Length == 0)) 
        return null; 

       string s = new string('\0', us.Length/2); 
       hr = NtWow64ReadVirtualMemory64(handle, us.Buffer, s, us.Length, IntPtr.Zero); 
       if (hr != 0) 
        throw new Win32Exception(hr); 

       return s; 
      } 
      else // we are running with the same bitness as the OS, 32 or 64 
      { 
       PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION(); 
       int hr = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); 
       if (hr != 0) 
        throw new Win32Exception(hr); 

       IntPtr pp = new IntPtr(); 
       if (!ReadProcessMemory(handle, pbi.PebBaseAddress + processParametersOffset, ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       UNICODE_STRING us = new UNICODE_STRING(); 
       if (!ReadProcessMemory(handle, pp + offset, ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       if ((us.Buffer == IntPtr.Zero) || (us.Length == 0)) 
        return null; 

       string s = new string('\0', us.Length/2); 
       if (!ReadProcessMemory(handle, us.Buffer, s, new IntPtr(us.Length), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       return s; 
      } 
     } 
     finally 
     { 
      CloseHandle(handle); 
     } 
    } 

    private const int PROCESS_QUERY_INFORMATION = 0x400; 
    private const int PROCESS_VM_READ = 0x10; 

    [StructLayout(LayoutKind.Sequential)] 
    private struct PROCESS_BASIC_INFORMATION 
    { 
     public IntPtr Reserved1; 
     public IntPtr PebBaseAddress; 
     public IntPtr Reserved2_0; 
     public IntPtr Reserved2_1; 
     public IntPtr UniqueProcessId; 
     public IntPtr Reserved3; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct UNICODE_STRING 
    { 
     public short Length; 
     public short MaximumLength; 
     public IntPtr Buffer; 
    } 

    // for 32-bit process in a 64-bit OS only 
    [StructLayout(LayoutKind.Sequential)] 
    private struct PROCESS_BASIC_INFORMATION_WOW64 
    { 
     public long Reserved1; 
     public long PebBaseAddress; 
     public long Reserved2_0; 
     public long Reserved2_1; 
     public long UniqueProcessId; 
     public long Reserved3; 
    } 

    // for 32-bit process in a 64-bit OS only 
    [StructLayout(LayoutKind.Sequential)] 
    private struct UNICODE_STRING_WOW64 
    { 
     public short Length; 
     public short MaximumLength; 
     public long Buffer; 
    } 

    [DllImport("ntdll.dll")] 
    private static extern int NtQueryInformationProcess(IntPtr ProcessHandle, int ProcessInformationClass, ref PROCESS_BASIC_INFORMATION ProcessInformation, int ProcessInformationLength, IntPtr ReturnLength); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref IntPtr lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref UNICODE_STRING lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [MarshalAs(UnmanagedType.LPWStr)] string lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); 

    [DllImport("kernel32.dll")] 
    private static extern bool CloseHandle(IntPtr hObject); 

    // for 32-bit process in a 64-bit OS only 
    [DllImport("ntdll.dll")] 
    private static extern int NtWow64QueryInformationProcess64(IntPtr ProcessHandle, int ProcessInformationClass, ref PROCESS_BASIC_INFORMATION_WOW64 ProcessInformation, int ProcessInformationLength, IntPtr ReturnLength); 

    [DllImport("ntdll.dll")] 
    private static extern int NtWow64ReadVirtualMemory64(IntPtr hProcess, long lpBaseAddress, ref long lpBuffer, long dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("ntdll.dll")] 
    private static extern int NtWow64ReadVirtualMemory64(IntPtr hProcess, long lpBaseAddress, ref UNICODE_STRING_WOW64 lpBuffer, long dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("ntdll.dll")] 
    private static extern int NtWow64ReadVirtualMemory64(IntPtr hProcess, long lpBaseAddress, [MarshalAs(UnmanagedType.LPWStr)] string lpBuffer, long dwSize, IntPtr lpNumberOfBytesRead); 
} 
+1

Penso che ci siano 4 possibili combinazioni di processi 32 vs 64 bit. È inoltre necessario IsWow64Process() per verificare se il processo di destinazione è a 32 bit. Oh gioia;) –

+0

@ HansPassant - Io non la penso così. Il codice è fatto per gestire le 3 combinazioni - non 64 su 32 ammetto :-), l'hai testato o l'hai guardato attentamente? –

+0

* NtWow64ReadVirtualMemory64 * non restituisce né un codice errore HRESULT né un errore Win32. Utilizzare * RtlNtStatusToDosError * per convertire il segnale del risultato in un codice di errore gettabile. – IllidanS4

0

Le origini "Simon Mourier" funzionano bene in SO, Executor, Target a 32 bit. Ma altri non lo sono. Quindi aggiungo sorgente per gestire tutte le combinazioni di 32, 64 bit. Ci sono 5 possibili combinazioni di processo a 32, 64 bit. Per prima cosa, os, executor, target sono 32bit. In secondo luogo, os è 64 bit, executor, obiettivo sono la combinazione di processo a 32,64 bit. Questo codice funziona perfettamente nel mio notebook Win7 64Bit OS, 32,64 bit Processo & target 32,64 bit Process, WinXp 32bit, exeutor, target sono 32 bit. Ma, utilizzare a proprio rischio!

// ref: http://www.microsoft.com/whdc/system/Sysinternals/MoreThan64proc.mspx 
public enum PROCESSINFOCLASS : int 
{ 
    ProcessBasicInformation = 0, // 0, q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION 
    ProcessWow64Information = 26, // q: ULONG_PTR 
} 
[Flags] 
public enum PEB_OFFSET 
{ 
    CurrentDirectory, 
    //DllPath, 
    //ImagePathName, 
    CommandLine, 
    //WindowTitle, 
    //DesktopInfo, 
    //ShellInfo, 
    //RuntimeData, 
    //TypeMask = 0xffff, 
    //Wow64 = 0x10000, 
}; 

public class Is64BitChecker 
{ 
    [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool IsWow64Process(
     [In] IntPtr hProcess, 
     [Out] out bool wow64Process 
    ); 

    public static bool GetProcessIsWow64(IntPtr hProcess) 
    { 
     if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) || 
      Environment.OSVersion.Version.Major >= 6) 
     { 
      bool retVal; 
      if (!IsWow64Process(hProcess, out retVal)) 
      { 
       return false; 
      } 
      return retVal; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public static bool InternalCheckIsWow64() 
    { 
     if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) || 
      Environment.OSVersion.Version.Major >= 6) 
     { 
      using (Process p = Process.GetCurrentProcess()) 
      { 
       bool retVal; 
       if (!IsWow64Process(p.Handle, out retVal)) 
       { 
        return false; 
       } 
       return retVal; 
      } 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

// All offset values below have been tested on Windows 7 & 8 only 
// but you can use WinDbg "dt ntdll!_PEB" command and search for ProcessParameters offset to find the truth, depending on the OS version 
public static class ProcessUtilities 
{ 
    public static readonly bool Is64BitProcess = IntPtr.Size > 4; 
    public static readonly bool Is64BitOperatingSystem = Is64BitProcess || Is64BitChecker.InternalCheckIsWow64(); 

    public static string GetCurrentDirectory(int processId) 
    { 
     return GetProcessParametersString(processId, PEB_OFFSET.CurrentDirectory); 
    } 

    public static string GetCurrentDirectory(this Process process) 
    { 
     if (process == null) 
      throw new ArgumentNullException("process"); 

     return GetCurrentDirectory(process.Id); 
    } 

    #region GetCommandLine 
    //public static string GetCommandLine(int processId) 
    //{ 
    // return null;// GetProcessParametersString(processId, Is64BitOperatingSystem ? 0x70 : 0x40); 
    //} 

    //public static string GetCommandLine(this Process process) 
    //{ 
    // if (process == null) 
    //  throw new ArgumentNullException("process"); 

    // return GetCommandLine(process.Id); 
    //} 
    #endregion 

    private static string GetProcessParametersString(int processId, PEB_OFFSET Offset) 
    { 
     IntPtr handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId); 
     if (handle == IntPtr.Zero) 
      throw new Win32Exception(Marshal.GetLastWin32Error()); 

     bool IsWow64Process = Is64BitChecker.InternalCheckIsWow64(); 
     bool IsTargetWow64Process = Is64BitChecker.GetProcessIsWow64(handle); 
     bool IsTarget64BitProcess = Is64BitOperatingSystem && !IsTargetWow64Process; 

     long offset = 0; 
     long processParametersOffset = IsTarget64BitProcess ? 0x20 : 0x10; 
     switch (Offset) 
     { 
      case PEB_OFFSET.CurrentDirectory: 
       offset = IsTarget64BitProcess ? 0x38 : 0x24; 
       break; 
      case PEB_OFFSET.CommandLine: 
      default: 
       return null; 
     } 

     try 
     { 
      long pebAddress = 0; 
      if (IsTargetWow64Process) // OS : 64Bit, Cur : 32 or 64, Tar: 32bit 
      { 
       IntPtr peb32 = new IntPtr(); 

       int hr = NtQueryInformationProcess(handle, (int)PROCESSINFOCLASS.ProcessWow64Information, ref peb32, IntPtr.Size, IntPtr.Zero); 
       if (hr != 0) throw new Win32Exception(hr); 
       pebAddress = peb32.ToInt64(); 

       IntPtr pp = new IntPtr(); 
       if (!ReadProcessMemory(handle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       UNICODE_STRING_32 us = new UNICODE_STRING_32(); 
       if (!ReadProcessMemory(handle, new IntPtr(pp.ToInt64() + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       if ((us.Buffer == 0) || (us.Length == 0)) 
        return null; 

       string s = new string('\0', us.Length/2); 
       if (!ReadProcessMemory(handle, new IntPtr(us.Buffer), s, new IntPtr(us.Length), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       return s; 
      } 
      else if (IsWow64Process)//Os : 64Bit, Cur 32, Tar 64 
      { 
       PROCESS_BASIC_INFORMATION_WOW64 pbi = new PROCESS_BASIC_INFORMATION_WOW64(); 
       int hr = NtWow64QueryInformationProcess64(handle, (int)PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); 
       if (hr != 0) throw new Win32Exception(hr); 
       pebAddress = pbi.PebBaseAddress; 

       long pp = 0; 
       hr = NtWow64ReadVirtualMemory64(handle, pebAddress + processParametersOffset, ref pp, Marshal.SizeOf(pp), IntPtr.Zero); 
       if (hr != 0) 
        throw new Win32Exception(hr); 

       UNICODE_STRING_WOW64 us = new UNICODE_STRING_WOW64(); 
       hr = NtWow64ReadVirtualMemory64(handle, pp + offset, ref us, Marshal.SizeOf(us), IntPtr.Zero); 
       if (hr != 0) 
        throw new Win32Exception(hr); 

       if ((us.Buffer == 0) || (us.Length == 0)) 
        return null; 

       string s = new string('\0', us.Length/2); 
       hr = NtWow64ReadVirtualMemory64(handle, us.Buffer, s, us.Length, IntPtr.Zero); 
       if (hr != 0) 
        throw new Win32Exception(hr); 

       return s; 
      } 
      else// Os,Cur,Tar : 64 or 32 
      { 
       PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION(); 
       int hr = NtQueryInformationProcess(handle, (int)PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); 
       if (hr != 0) throw new Win32Exception(hr); 
       pebAddress = pbi.PebBaseAddress.ToInt64(); 

       IntPtr pp = new IntPtr(); 
       if (!ReadProcessMemory(handle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       UNICODE_STRING us = new UNICODE_STRING(); 
       if (!ReadProcessMemory(handle, new IntPtr((long)pp + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       if ((us.Buffer == IntPtr.Zero) || (us.Length == 0)) 
        return null; 

       string s = new string('\0', us.Length/2); 
       if (!ReadProcessMemory(handle, us.Buffer, s, new IntPtr(us.Length), IntPtr.Zero)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       return s; 
      } 
     } 
     finally 
     { 
      CloseHandle(handle); 
     } 
    } 

    private const int PROCESS_QUERY_INFORMATION = 0x400; 
    private const int PROCESS_VM_READ = 0x10; 

    [StructLayout(LayoutKind.Sequential)] 
    private struct PROCESS_BASIC_INFORMATION 
    { 
     public IntPtr Reserved1; 
     public IntPtr PebBaseAddress; 
     public IntPtr Reserved2_0; 
     public IntPtr Reserved2_1; 
     public IntPtr UniqueProcessId; 
     public IntPtr Reserved3; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct UNICODE_STRING 
    { 
     public short Length; 
     public short MaximumLength; 
     public IntPtr Buffer; 
    } 

    // for 32-bit process in a 64-bit OS only 
    [StructLayout(LayoutKind.Sequential)] 
    private struct PROCESS_BASIC_INFORMATION_WOW64 
    { 
     public long Reserved1; 
     public long PebBaseAddress; 
     public long Reserved2_0; 
     public long Reserved2_1; 
     public long UniqueProcessId; 
     public long Reserved3; 
    } 

    // for 32-bit process 
    [StructLayout(LayoutKind.Sequential)] 
    private struct UNICODE_STRING_WOW64 
    { 
     public short Length; 
     public short MaximumLength; 
     public long Buffer; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct UNICODE_STRING_32 
    { 
     public short Length; 
     public short MaximumLength; 
     public int Buffer; 
    } 

    [DllImport("ntdll.dll")] 
    private static extern int NtQueryInformationProcess(IntPtr ProcessHandle, int ProcessInformationClass, ref PROCESS_BASIC_INFORMATION ProcessInformation, int ProcessInformationLength, IntPtr ReturnLength); 

    //ProcessWow64Information, // q: ULONG_PTR 
    [DllImport("ntdll.dll")] 
    private static extern int NtQueryInformationProcess(IntPtr ProcessHandle, int ProcessInformationClass, ref IntPtr ProcessInformation, int ProcessInformationLength, IntPtr ReturnLength); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref IntPtr lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref UNICODE_STRING lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref UNICODE_STRING_32 lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead); 

    //[DllImport("kernel32.dll", SetLastError = true)] 
    //private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref UNICODE_STRING_WOW64 lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [MarshalAs(UnmanagedType.LPWStr)] string lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); 

    [DllImport("kernel32.dll")] 
    private static extern bool CloseHandle(IntPtr hObject); 

    // for 32-bit process in a 64-bit OS only 
    [DllImport("ntdll.dll")] 
    private static extern int NtWow64QueryInformationProcess64(IntPtr ProcessHandle, int ProcessInformationClass, ref PROCESS_BASIC_INFORMATION_WOW64 ProcessInformation, int ProcessInformationLength, IntPtr ReturnLength); 

    [DllImport("ntdll.dll")] 
    private static extern int NtWow64ReadVirtualMemory64(IntPtr hProcess, long lpBaseAddress, ref long lpBuffer, long dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("ntdll.dll")] 
    private static extern int NtWow64ReadVirtualMemory64(IntPtr hProcess, long lpBaseAddress, ref UNICODE_STRING_WOW64 lpBuffer, long dwSize, IntPtr lpNumberOfBytesRead); 

    [DllImport("ntdll.dll")] 
    private static extern int NtWow64ReadVirtualMemory64(IntPtr hProcess, long lpBaseAddress, [MarshalAs(UnmanagedType.LPWStr)] string lpBuffer, long dwSize, IntPtr lpNumberOfBytesRead); 
}