我尝试在Windows 7中获取另一个进程的命令行参数。我使用this article作为参考。
但是返回错误总是给我(NTSTATUS dwStatus
)负数,如:
dwStatus = -1073741820
进程ID有效,apa = GetLastError();
为S_OK
这是我的代码:
头文件
class NtDll
{
...
typedef DWORD (WINAPI *PNtQueryInformationProcess)(HANDLE, DWORD, PVOID, DWORD, PVOID );
static PNtQueryInformationProcess NtQueryInformationProcess;
....
....
}
c ++文件
i do this to enable access :
//== only to have better chance to read processes =====
if(!sm_EnableTokenPrivilege(SE_DEBUG_NAME))
{
return 0;
}
// Attempt to access process
BOOL bReturnStatus = TRUE;
DWORD dwSize = 0;
DWORD dwSizeNeeded = 0;
DWORD dwBytesRead = 0;
DWORD dwBufferSize = 0;
HANDLE hHeap = 0;
WCHAR *pwszBuffer = NULL;
smPROCESSINFO spi = {0};
smPPROCESS_BASIC_INFORMATION pbi = NULL;
smPEB peb = {0};
smPEB_LDR_DATA peb_ldr = {0};
smRTL_USER_PROCESS_PARAMETERS peb_upp = {0};
ZeroMemory(&spi, sizeof(spi));
ZeroMemory(&peb, sizeof(peb));
ZeroMemory(&peb_ldr, sizeof(peb_ldr));
ZeroMemory(&peb_upp, sizeof(peb_upp));
// pSysProcess->dUniqueProcessId is the process number
HRESULT apa = 0;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ, FALSE,pSysProcess->dUniqueProcessId);
if(hProcess == INVALID_HANDLE_VALUE) {
return FALSE;
}
else if(hProcess == NULL)
{
apa = GetLastError();
}
// Try to allocate buffer
hHeap = GetProcessHeap();
dwSize = sizeof(smPPROCESS_BASIC_INFORMATION);
pbi = (smPPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap,
HEAP_ZERO_MEMORY,
dwSize);
// Did we successfully allocate memory
if(!pbi) {
CloseHandle(hProcess);
return FALSE;
}
// Attempt to get basic info on process
NTSTATUS dwStatus = NtDll::NtQueryInformationProcess(hProcess,
ProcessBasicInformation,
pbi,
dwSize,
&dwSizeNeeded);
HRESULT dwStatus_err = 0;
dwStatus_err = GetLastError(); // This gives me always access denied
一切似乎都是正确的,但我仍然得到错误的结果,为什么会这样?
更新:
我添加了指示我做了sm_EnableTokenPrivilege 并且:
dwStatus_err = GetLastError(); // This gives me always access denied
答案 0 :(得分:3)
获取进程命令行参数的简单方法:
WMIC path win32_process get Caption,Processid,Commandline
通过代码的另一种方式(见article):
VOID GetCommandLines()
{
HRESULT hr = 0;
IWbemLocator *WbemLocator = NULL;
IWbemServices *WbemServices = NULL;
IEnumWbemClassObject *EnumWbem = NULL;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you need to specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &WbemLocator);
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
hr = WbemLocator->ConnectServer(L"ROOT\\CIMV2", NULL, NULL, NULL, 0, NULL, NULL, &WbemServices);
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hr = CoSetProxyBlanket(WbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
hr = WbemServices->ExecQuery(L"WQL", L"SELECT ProcessId,CommandLine FROM Win32_Process", WBEM_FLAG_FORWARD_ONLY, NULL, &EnumWbem);
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
if (EnumWbem != NULL) {
IWbemClassObject *result = NULL;
ULONG returnedCount = 0;
while((hr = EnumWbem->Next(WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
VARIANT ProcessId;
VARIANT CommandLine;
// access the properties
hr = result->Get(L"ProcessId", 0, &ProcessId, 0, 0);
hr = result->Get(L"CommandLine", 0, &CommandLine, 0, 0);
if (!(CommandLine.vt==VT_NULL))
wprintf(L"%u %s \r\n", ProcessId.uintVal, CommandLine.bstrVal);
result->Release();
}
}
// Cleanup
// ========
EnumWbem->Release();
WbemServices->Release();
WbemLocator->Release();
CoUninitialize();
getchar();
}
如果您真的想让NtQueryInformationProcess正常工作,请参阅此blog entry或此file。
DWORD GetRemoteCommandLineW(HANDLE hProcess, LPWSTR pszBuffer, UINT bufferLength)
{
struct RTL_USER_PROCESS_PARAMETERS_I
{
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
};
struct PEB_INTERNAL
{
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
struct PEB_LDR_DATA* Ldr;
RTL_USER_PROCESS_PARAMETERS_I* ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
struct PS_POST_PROCESS_INIT_ROUTINE* PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
};
typedef NTSTATUS (NTAPI* NtQueryInformationProcessPtr)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL);
typedef ULONG (NTAPI* RtlNtStatusToDosErrorPtr)(NTSTATUS Status);
// Locating functions
HINSTANCE hNtDll = GetModuleHandleW(L"ntdll.dll");
NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hNtDll, "NtQueryInformationProcess");
RtlNtStatusToDosErrorPtr RtlNtStatusToDosError = (RtlNtStatusToDosErrorPtr)GetProcAddress(hNtDll, "RtlNtStatusToDosError");
if(!NtQueryInformationProcess || !RtlNtStatusToDosError)
{
printf("Functions cannot be located.\n");
return 0;
}
// Get PROCESS_BASIC_INFORMATION
PROCESS_BASIC_INFORMATION pbi;
ULONG len;
NTSTATUS status = NtQueryInformationProcess(
hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &len);
SetLastError(RtlNtStatusToDosError(status));
if(NT_ERROR(status) || !pbi.PebBaseAddress)
{
printf("NtQueryInformationProcess(ProcessBasicInformation) failed.\n");
return 0;
}
// Read PEB memory block
SIZE_T bytesRead = 0;
PEB_INTERNAL peb;
if(!ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), &bytesRead))
{
printf("Reading PEB failed.\n");
return 0;
}
// Obtain size of commandline string
RTL_USER_PROCESS_PARAMETERS_I upp;
if(!ReadProcessMemory(hProcess, peb.ProcessParameters, &upp, sizeof(upp), &bytesRead))
{
printf("Reading USER_PROCESS_PARAMETERS failed.\n");
return 0;
}
if(!upp.CommandLine.Length)
{
printf("Command line length is 0.\n");
return 0;
}
// Check the buffer size
DWORD dwNeedLength = (upp.CommandLine.Length+1) / sizeof(wchar_t) +1;
if(bufferLength < dwNeedLength)
{
printf("Not enough buffer.\n");
return dwNeedLength;
}
// Get the actual command line
pszBuffer[dwNeedLength - 1] = L'\0';
if(!ReadProcessMemory(hProcess, upp.CommandLine.Buffer, pszBuffer, upp.CommandLine.Length, &bytesRead))
{
printf("Reading command line failed.\n");
return 0;
}
return bytesRead / sizeof(wchar_t);
}