2016-06-19 4 views
-8

私はプロセス環境の文字列を取得しようとしていますが、以下のコードは私がすでに書いたものです。他のプロセスの環境変数を読む

#include <windows.h> 
#include <tchar.h> 

#define ProcessBasicInformation 0 

typedef struct _PROCESS_BASIC_INFORMATION { 
    NTSTATUS ExitStatus; 
    PVOID  PebBaseAddress; 
    ULONG_PTR AffinityMask; 
    LONG  BasePriority; 
    HANDLE UniqueProcessId; 
    HANDLE InheritedFromUniqueProcessId; 
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; 

int _tmain(int argc, TCHAR* argv[]) { 
    TCHAR *app; 
    DWORD pid; 
    HANDLE proc; 
    NTSTATUS nts; 
    PVOID rupp; // RTL_USER_PROCESS_PARAMETERS, offset 0x10 
    PVOID env; // Environment, offset 0x48 
    TCHAR *buf; 
    PROCESS_BASIC_INFORMATION pbi; 
    MEMORY_BASIC_INFORMATION mbi; 

    if (argc != 2) { 
    app = _tcsrchr(argv[0], '\\'); 
    _tprintf(TEXT("Usage: %s [PID]\n"), app ? ++app : argv[0]); 
    return -1; 
    } 

    _stscanf_s(argv[1], TEXT("%lu"), &pid); 
    if (!(proc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid))) { 
    return -1; 
    } 

    if (!(nts = NtQueryInformationProcess(
    proc, ProcessBasicInformation, &pbi, sizeof(pbi), NULL 
    ))) { 
    if (ReadProcessMemory(
    proc, (PCHAR)pbi.PebBaseAddress + 0x10, &rupp, sizeof(rupp), NULL 
    )) { 
    if (ReadProcessMemory(proc, (PCHAR)rupp + 0x48, &env, sizeof(env), NULL)) { 
    //what I need to do to get enironment strings? 
    } 
} 
    } 

    CloseHandle(proc); 

    return 0; 
} 

誰かがプロセスの環境文字列を取得するために必要なことを誰かが説明できますか?

+0

https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx –

+0

@OliverCharlesworth 'GetEnvironmentVariable'は、呼び出し元のプロセスの環境を得ることです、OPは別のリモートプロセスの環境を取得したい。 – fluter

+1

私はこれを行うためのサポートされている方法に気づいていません。環境変数を保護するロックはプロセスローカルです。別のプロセスからロックを取得することはできません。環境変数はプロセスにとってプライベートであるとみなされ、外部的に操作されるべきではありません。プロセスの環境変数を操作する場合は、プロセスと調整する必要があります。 (たとえば、[環境設定]の[WM_SETTINGSCHANGE]通知(https://msdn.microsoft.com/en-us/library/windows/desktop/ms725497(v = vs.85).aspxを参照してください) –

答えて

0

まずx86のコードのみですが、x64システムはどうですか? x64では、x64プロセスのアクセス環境のためにx64コードから実行する必要があります。しかし、Wow64プロセスはどうですか?彼らは2つの環境を持っています! 1ナイーブと1ワウとこれは等しい文字列ではありません。タスクが十分に複雑になる可能性があります。しかし、もちろん存在します。

NTSTATUS ReadProcessEnv(HANDLE hProcess, PVOID Environment, PWSTR* ppsz) 
{ 
    NTSTATUS status; 
    MEMORY_BASIC_INFORMATION mbi; 

    if (0 > (status = ZwQueryVirtualMemory(hProcess, Environment, MemoryBasicInformation, &mbi, sizeof(mbi), 0))) return status; 

    if (mbi.State != MEM_COMMIT || mbi.Type != MEM_PRIVATE) 
    { 
     return STATUS_UNSUCCESSFUL; 
    } 

    mbi.RegionSize -= RtlPointerToOffset(mbi.BaseAddress, Environment); 

    //Environment must be WCHAR aligned and how minimum 2*sizeof(WCHAR) size 
    if (mbi.RegionSize < 2*sizeof(WCHAR) || ((ULONG_PTR)Environment & (__alignof(WCHAR) - 1))) 
    { 
     return STATUS_UNSUCCESSFUL; 
    } 

    if (mbi.RegionSize > 0x10000)// >64Kb Environment ?? 
    { 
     mbi.RegionSize = 0x10000; 
    } 

    if (PWSTR buf = new WCHAR[mbi.RegionSize]) 
    { 
     if (0 <= (status = ZwReadVirtualMemory(hProcess, Environment, buf, mbi.RegionSize, 0))) 
     { 
      buf[mbi.RegionSize - 2] = 0; 
      buf[mbi.RegionSize - 1] = 0; 
      *ppsz = buf; 

      return STATUS_SUCCESS; 
     } 
     delete buf; 

     return status; 
    } 

    return STATUS_INSUFFICIENT_RESOURCES; 
} 

NTSTATUS ReadProcessEnv(HANDLE hProcess, PWSTR* ppsz) 
{ 
    NTSTATUS status; 
    PROCESS_BASIC_INFORMATION pbi; 
    _RTL_USER_PROCESS_PARAMETERS* ProcessParameters; 
    PVOID Environment; 

    if (
     0 > (status = ZwQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), 0)) 
     || 
     0 > (status = ZwReadVirtualMemory(hProcess, &pbi.PebBaseAddress->ProcessParameters, &ProcessParameters, sizeof(PVOID), 0)) 
     || 
     0 > (status = ZwReadVirtualMemory(hProcess, &ProcessParameters->Environment, &Environment, sizeof(PVOID), 0)) 
     ) 
     return status; 

    return ReadProcessEnv(hProcess, Environment, ppsz); 
} 

#ifdef _WIN64 

NTSTATUS ReadProcessEnvWow(HANDLE hProcess, PWSTR* ppsz) 
{ 
    ULONG WowPeb, ProcessParameters; 
    NTSTATUS status; 
    PVOID Environment = 0; 

    if (0 > (status = ZwQueryInformationProcess(hProcess, ProcessWow64Information, &WowPeb, sizeof(PVOID), 0))) return status; 

    if (!WowPeb) 
    { 
     return STATUS_SUCCESS; 
    } 

    enum { 
     ofs32_ProcessParameters = 0x10, 
     ofs32_Environment = 0x48 
    }; 

    if (
     0 > (status = ZwReadVirtualMemory(hProcess, RtlOffsetToPointer(WowPeb, ofs32_ProcessParameters), &ProcessParameters, sizeof(ULONG), 0)) 
     || 
     0 > (status = ZwReadVirtualMemory(hProcess, RtlOffsetToPointer(ProcessParameters, ofs32_Environment), &Environment, sizeof(ULONG), 0)) 
     ) 
     return status; 

    return ReadProcessEnv(hProcess, Environment, ppsz); 
} 
#endif 

NTSTATUS ReadProcessEnv(
         PCLIENT_ID cid, 
         PWSTR* ppsz, 
         PNTSTATUS pstatus 
#ifdef _WIN64 
         , 
         PWSTR* ppszWow, 
         PNTSTATUS pstatusWow 
#endif 
         ) 
{ 
    HANDLE hProcess; 
    NTSTATUS status = ZwOpenProcess(&hProcess, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, &zoa, cid); 

    if (0 <= status) 
    { 
     *ppsz = 0; 
     *pstatus = ReadProcessEnv(hProcess, ppsz); 
#ifdef _WIN64 
     *ppszWow = 0; 
     *pstatusWow = ReadProcessEnvWow(hProcess, ppszWow); 
#endif 
     ZwClose(hProcess); 
    } 

    return status; 
} 

void DumpEnv(PCWSTR sz) 
{ 
    while (*sz) 
    { 
     DbgPrint("%S\n", sz); 
     sz += wcslen(sz) + 1; 
    } 
} 

void test(PCLIENT_ID cid) 
{ 
    PWSTR env, envWow; 
    NTSTATUS status, s; 

#ifdef _WIN64 
    NTSTATUS sWow; 
#endif 

    if (0 <= (status = ReadProcessEnv(cid, &env, &s 
#ifdef _WIN64 
     , &envWow, &sWow 
#endif 
     ))) 
    { 
     if (0 <= s) 
     { 
      DumpEnv(env); 
      delete env; 
     } 

#ifdef _WIN64 
     if (0 <= sWow) 
     { 
      if (envWow) 
      { 
       DumpEnv(envWow); 
       delete envWow; 
      } 
     } 
#endif 
    } 
} 
+0

私はx64のコードは必要ありません、私は何とか自分のコードでbufから行を抽出する必要があります。 – kate

+0

抽出行の見方 - 見た目 - void DumpEnv(PCWSTR sz) - それは行vy行をダンプします。いくつかの名前で名前を変更する必要がある場合 - RtlQueryEnvironmentVariable_UまたはRtlQueryEnvironmentVariableを使用してください – RbMm

+0

DumpEnvは最初の変数を取得し、他は失われます。私はクエリ変数を必要としません、私はちょうどプロセスの変数を取得する必要があります。 – kate