#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
typedef
struct
_PROCESS_BASIC_INFORMATION
{
PVOID
Reserved1;
PVOID
PebBaseAddress;
PVOID
Reserved2[2];
ULONG_PTR
UniqueProcessId;
PVOID
Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef
struct
_PROCESS_BASIC_INFORMATION_WOW64
{
PVOID
Reserved1[2];
PVOID64 PebBaseAddress;
PVOID
Reserved2[4];
ULONG_PTR
UniqueProcessId[2];
PVOID
Reserved3[2];
} PROCESS_BASIC_INFORMATION_WOW64;
typedef
struct
_UNICODE_STRING
{
USHORT
Length;
USHORT
MaximumLength;
PWSTR
Buffer;
} UNICODE_STRING;
typedef
struct
_UNICODE_STRING_WOW64
{
USHORT
Length;
USHORT
MaximumLength;
PVOID64 Buffer;
} UNICODE_STRING_WOW64;
wchar_t
*GetProcessPebCommandLine(
DWORD
dwProcessId )
{
NTSTATUS status;
SYSTEM_INFO si;
BOOL
wow64;
HANDLE
hProcess = NULL;
wchar_t
*pCmdLine = NULL;
PBYTE
peb = NULL;
PBYTE
pUserProcessParameters = NULL;
do
{
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
if
( hProcess == NULL )
{
assert
(FALSE);
break
;
}
GetNativeSystemInfo( &si );
IsWow64Process( GetCurrentProcess(), &wow64 );
DWORD
ProcessParametersOffset = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? 0x20 : 0x10;
DWORD
CommandLineOffset = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? 0x70 : 0x40;
DWORD
pebSize = ProcessParametersOffset + 8;
DWORD
ppSize = CommandLineOffset + 16;
peb = (
PBYTE
)
malloc
( pebSize * 2 );
pUserProcessParameters = (
PBYTE
)
malloc
( ppSize * 2 );
if
( peb == NULL || pUserProcessParameters == NULL )
{
assert
( FALSE );
break
;
}
ZeroMemory( pUserProcessParameters, ppSize );
ZeroMemory( peb, pebSize );
if
( wow64 )
{
PROCESS_BASIC_INFORMATION_WOW64 pbi;
ZeroMemory( &pbi,
sizeof
( pbi ) );
typedef
NTSTATUS( __stdcall * fnNtWow64QueryInformationProcess64 )(
HANDLE
ProcessHandle,
ULONG
ProcessInformationClass,
PVOID
ProcessInformation,
ULONG
ProcessInformationLength,
PULONG
ReturnLength );
static
fnNtWow64QueryInformationProcess64 pNtWow64QueryInformationProcess64 = ( fnNtWow64QueryInformationProcess64 )GetProcAddress( GetModuleHandleA(
"ntdll.dll"
),
"NtWow64QueryInformationProcess64"
);
typedef
NTSTATUS( __stdcall * fnNtWow64ReadVirtualMemory64 )(
HANDLE
ProcessHandle, PVOID64 BaseAddress,
PVOID
Buffer,
ULONG64
Size,
PULONG64
NumberOfBytesRead );
static
fnNtWow64ReadVirtualMemory64 pfnWow64ReadVirtualMemory64 = ( fnNtWow64ReadVirtualMemory64 )GetProcAddress( GetModuleHandleA(
"ntdll.dll"
),
"NtWow64ReadVirtualMemory64"
);
if
( pNtWow64QueryInformationProcess64 == NULL || pfnWow64ReadVirtualMemory64 == NULL )
{
assert
( FALSE );
break
;
}
status = pNtWow64QueryInformationProcess64( hProcess, 0, &pbi,
sizeof
( pbi ), NULL );
if
( !NT_SUCCESS( status ) )
{
assert
( FALSE );
break
;
}
status = pfnWow64ReadVirtualMemory64( hProcess, pbi.PebBaseAddress, peb, pebSize, NULL );
if
( !NT_SUCCESS( status ) )
{
assert
( FALSE );
break
;
}
PBYTE
*parameters = (
PBYTE
* ) * (
LPVOID
* )( peb + ProcessParametersOffset );
status = pfnWow64ReadVirtualMemory64( hProcess, parameters, pUserProcessParameters, ppSize, NULL );
if
( !NT_SUCCESS( status ) )
{
assert
(FALSE);
break
;
}
UNICODE_STRING_WOW64 *pCommandLine = ( UNICODE_STRING_WOW64 * )( pUserProcessParameters + CommandLineOffset );
pCmdLine = (
PWSTR
)
malloc
( pCommandLine->MaximumLength * 2 );
status = pfnWow64ReadVirtualMemory64( hProcess, pCommandLine->Buffer, pCmdLine, pCommandLine->MaximumLength, NULL );
if
( !NT_SUCCESS( status ) )
{
assert
( FALSE );
break
;
}
}
else
{
PROCESS_BASIC_INFORMATION pbi;
ZeroMemory( &pbi,
sizeof
( pbi ) );
typedef
NTSTATUS( __stdcall * fnZwQueryInformationProcess )(
HANDLE
ProcessHandle,
ULONG
ProcessInformationClass,
PVOID
ProcessInformation,
ULONG
ProcessInformationLength,
PULONG
ReturnLength );
static
fnZwQueryInformationProcess pZwQueryInformationProcess = ( fnZwQueryInformationProcess )GetProcAddress( GetModuleHandleA(
"ntdll.dll"
),
"ZwQueryInformationProcess"
);
if
( pZwQueryInformationProcess == NULL )
{
assert
( FALSE );
break
;
}
status = pZwQueryInformationProcess( hProcess, 0, &pbi,
sizeof
( pbi ), NULL );
if
( !NT_SUCCESS( status ) )
{
assert
( FALSE );
break
;
}
if
( !ReadProcessMemory( hProcess, pbi.PebBaseAddress, peb, pebSize, NULL ) )
{
assert
(FALSE);
break
;
}
PBYTE
*parameters = (
PBYTE
* ) * (
LPVOID
* )( peb + ProcessParametersOffset );
if
( !ReadProcessMemory( hProcess, parameters, pUserProcessParameters, ppSize, NULL ) )
{
assert
( FALSE );
break
;
}
UNICODE_STRING *pCommandLine = ( UNICODE_STRING * )( pUserProcessParameters + CommandLineOffset );
pCmdLine = (
PWSTR
)
malloc
( pCommandLine->MaximumLength * 2 );
if
( pCmdLine == NULL )
{
assert
( FALSE );
break
;
}
ZeroMemory( pCmdLine, pCommandLine->MaximumLength );
if
( !ReadProcessMemory( hProcess, pCommandLine->Buffer, pCmdLine, pCommandLine->MaximumLength, NULL ) )
{
assert
( FALSE );
break
;
}
}
}
while
( FALSE );
SafeFreeBuffer( pUserProcessParameters );
SafeFreeBuffer( peb );
SafeCloseHandle( hProcess );
return
pCmdLine;
}