Otwarcie procesu z SeDebugPrivilege

0

Witam,
Chce otworzyć pewien proces, by odczytać pewną wartość z pamięci.
Otwarcie procesu z flagą PROCESS_VM_READ jest niemożliwe.
Jednak wyczytałem w MSDN, że można taki proces otworzyć nakładając mu przywilej SeDebugPrivilege.

Jednego pojąć nie moge.
Do funkcji OpenProcessToken musze przekazać HANDLE procesu, którego nie mogę otworzyć.
http://msdn.microsoft.com/en-us/library/aa379295(VS.85).aspx

Oczywiście wystarczy ten proces otworzyć z flagą PROCESS_QUERY_INFORMATION i taki HANDLE przekazać do OpenProcessToken. Jednak również OpenProcess dla mojego procesu daje False.
Czy coś w kodzie namieszałem, czy mam jakiś super zabezpieczony proces?

#include <windows.h>
#include <iostream>
#include <conio.h>

LPCWSTR lpstrWindowName = L"WindowName";
HWND hWindow;
DWORD dwProcess;
HANDLE hProcess;
int value = 0;
DWORD* pointer = (DWORD*)0x00540240;
HANDLE hToken;

BOOL SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
    ) 
{
	TOKEN_PRIVILEGES tp;
	LUID luid;

	if ( !LookupPrivilegeValue( 
			NULL,            // lookup privilege on local system
			lpszPrivilege,   // privilege to lookup 
			&luid ) )        // receives LUID of privilege
	{
		printf("LookupPrivilegeValue error: %u\n", GetLastError() ); 
		return FALSE; 
	}

	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	if (bEnablePrivilege)
		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	else
		tp.Privileges[0].Attributes = 0;

	// Enable the privilege or disable all privileges.

	if ( !AdjustTokenPrivileges(
		   hToken, 
		   FALSE, 
		   &tp, 
		   sizeof(TOKEN_PRIVILEGES), 
		   (PTOKEN_PRIVILEGES) NULL, 
		   (PDWORD) NULL) )
	{ 
		  printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); 
		  return FALSE; 
	} 

	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)

	{
		  printf("The token does not have the specified privilege. \n");
		  return FALSE;
	} 

	return TRUE;
}

int main()
{	
	if (!(hWindow = FindWindow(NULL, lpstrWindowName)))
		printf ("Window not found\n");
		
	if (!GetWindowThreadProcessId(hWindow, &dwProcess))
		printf ("Process not found\n");	
	
	if (!(hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, dwProcess)))
		printf ("Cant open process! \n");

	if(!OpenProcessToken(hProcess,/*TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY*/TOKEN_ADJUST_PRIVILEGES,&hToken))
        printf ("Cannot open process token\n");	
	SetPrivilege(hToken, SE_DEBUG_NAME, true);
	
	if (!ReadProcessMemory(hProcess, pointer, &value, 4, NULL))
	{
		printf ("Cant read in: 0x00%X \n", pointer);
		printf ("Error: %d\n", GetLastError());
	}
	else
	{
		printf ("Memory: %s \n", value);
	}

	getch();
	return 0;
}
Cant open process!
Cannot open process token
AdjustTokenPrivileges error: 6
Cant read in: 0x00740240
Error: 6
0

Próbowałeś na innym procesie?
Co zwraca GetLastError po nieudanej próbie otwarcia procesu?
Masz uprawnienia administratora? Jakiego masz Windows'a?

0

A może tak spróbować otworzyć inny proces, kiedy samemu się ma SeDebugPrivilege? Znaczy się, musisz pobrać token SWOJEGO procesu (patrz OpenProcessToken(GetCurrentProcess(), pozostałe argi)), ustawić przywilej SeDebugPrivilege, a potem próbować otwierać procesy, wątki, konserwy itp. Na bank zadziała, chyba, że coś wyjątkowo popsujesz :>

0

@adf88
GetLastError zwraca 6.
Wszystko jest tak jak powinno.

Testowałem na innym procesie i wszystko działa poprawnie.
Problem polega na tym, że mój proces jest zabezpieczony przed FindWindow ;).

@Fanael
A czy przypadkiem SeDebugPrivilege nie nadaję się osobno dla każdego z procesów?

W sumie zrobiłem to inaczej, skoro nie moge uzyskać ID mojego procesu to zrobiłem snapshot i stamtąd zgarnełem mój proces.
Jednak zjadł mnie taki banał. Jak porównać dwie zmienne tekstowe typu wchar_t? ;)

PROCESSENTRY32 pe32;
wchar_t cProcessName[260] = L"term.exe";
//.......................
HANDLE hProcessSnap;

do
if (pe32.szExeFile == cProcessName)
 return pe32.th32ProcessID;
while (Process32Next( hProcessSnap, &pe32 ))
// .........................
 return false;

Debugowałem kod i w momencie kiedy proces nazywa się term.exe (zmienna p32.szExeFile) to if nadal nie uznaje że są takie same jak cProcessName. Nie wiem jak to załatwić ;d

0

Tak, nadaje się każdemu osobno. Ale jakbyś przeczytał MSDN, to byś widział, że OpenProcess się wywala, jeśli caller nie ma SeDebugPrivilege... Zrób to, o czym mówiłem, zamiast robić jakieś chore workaroundy, dopiero jak nie będzie działać, to mów, że nie działa.
Hm... Porównanie wcharowych cstringów... lstrcmpW?
A można wiedzieć, po co ten ID twojego procesu? Możesz sobie wyciągnąć uchwyt do niego przecież (GetCurrentProcess()).

0

Ale jakbyś przeczytał MSDN, to byś widział, że OpenProcess się wywala, jeśli caller nie ma SeDebugPrivilege

To open a handle to another local process and obtain full access rights, you must enable the SeDebugPrivilege privilege.

Jeżeli chodzi Ci o tą linijkę to nie jest tu wyraźnie napisane, w którym procesie trzeba ustawić przywilej SeDebug.

A można wiedzieć, po co ten ID twojego procesu? Możesz sobie wyciągnąć uchwyt do niego przecież (GetCurrentProcess()).

Chce odczytać pamięć w nie moim procesie, dlatego najpierw potrzebuje znależć jego ID.

Hm... Porównanie wcharowych cstringów... lstrcmpW?

Dziękuje ;)

Zrób to, o czym mówiłem, zamiast robić jakieś chore workaroundy, dopiero jak nie będzie działać, to mów, że nie działa.

Ustawiłem dla siebie SeDebugPrivilege, mimo to nie mogę otworzyć tego drugiego procesu z flagą PROCESS_QUERY_INFORMATION.

DWORD dwProcess; // ID mojego procesu
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
		
	SetPrivilege(hToken, SE_DEBUG_NAME, true);

	if (!(hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, dwProcess)))
	{		
		printError(L"OpenProcess");
	}

	if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES,&hToken))
        printError(L"OpenProcessToken");

OpenProcess failed, error 5 - Odmowa dostępu

Jest jakaś inna metoda na otwarcie tego procesu? ;)

0
Fanael napisał(a)

A może tak spróbować otworzyć inny proces, kiedy samemu się ma SeDebugPrivilege? Znaczy się, musisz pobrać token SWOJEGO procesu (patrz OpenProcessToken(GetCurrentProcess(), pozostałe argi)), ustawić przywilej SeDebugPrivilege, a potem próbować otwierać procesy, wątki, konserwy itp. Na bank zadziała, chyba, że coś wyjątkowo popsujesz :>
Zgadza się, zbyt pobieżnie przeglądnąłem wypowiedź. Tak jak Fanael mówi, ustaw SeDebugPrivilege swojemu procesowi a następnie otwórz proces do którego się chcesz dostać z prawem PROCESS_VM_READ | co_tam_potrzebujesz (zaleca się używania minimalnego zestawu praw).
Czyli najpierw nadajesz sobie uprawnienie:

OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
SetPrivilege(hToken, SE_DEBUG_NAME, true);
CloaseHandle(hToken);

następnie otwierasz inny proces:

        if (!(hWindow = FindWindow(NULL, lpstrWindowName)))
                printf ("Window not found\n");
               
        if (!GetWindowThreadProcessId(hWindow, &dwProcess))
                printf ("Process not found\n");       
       
        if (!(hProcess = OpenProcess(PROCESS_VM_READ, false, dwProcess)))
                printf ("Cant open process! \n");

i grzebiesz w bebechach

        if (!ReadProcessMemory(hProcess, pointer, &value, 4, NULL))
        {
                printf ("Cant read in: 0x00%X \n", pointer);
                printf ("Error: %d\n", GetLastError());
        }
        else
        {
                printf ("Memory: %s \n", value);
        }
0

Tak jak już napisałem w poście wyżej. Dokładnie tak zrobiłem ;).
Niestety bez skutku, dalej odmowa dostępu.
Dodam, że funkcja nadająca przywilej SeDebugPrivilege mojemu procesowi zwraca true.
Mam uprawnienia administratora w systemie, zresztą inne procesy da rade tak otworzyć, tylko tego jednego nie na którym mi zależy. :/

0
tMbRaga napisał(a)

Tak jak już napisałem w poście wyżej. Dokładnie tak zrobiłem ;).
W poście napisałeś:

DWORD dwProcess; // ID mojego procesu
...
if (!(hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, dwProcess)))
czyli tak, jakbyś podawał nie to ID co trzeba.

0

Chwila, bo już samemu mi się miesza.
HANDLE z mojego procesu otrzymałem z GetCurrentProcess(). Przekazuje do OpenProcessToken() i nadaje przywilej SeDebugPrivilege.
Następnie otwieram przez OpenProcess() ten proces, do którego chce uzyskać dostęp (oddzielna aplikacja). Bezskutecznie.

Nie muszę używać OpenProcess względem mojego procesu tak? ... bo HANDLE już posiadam.

EDIT:
Próbowałem też -> OpenProcess(PROCESS_QUERY_INFORMATION, false,GetCurrentProcessID()).
Następnie nadawałem uprawnienia. (W sumie to samo co wyżej, tylko bardziej namieszane)
Niestety nadal tamtego procesu otworzyć nie mogę.

0

Otwórz go za pomocą DuplicateHandle zamiast OpenProcess:

#include <windows.h>

typedef DWORD (__stdcall *CSRPID)(void);
typedef DWORD (__stdcall *NTQSI)(ULONG SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength, ULONG* ReturnLength);
#define SystemHandleInformation 16

typedef struct {
    ULONG OwnerPid;
    BYTE ObjectType;
    BYTE HandleFlags;
    USHORT HandleValue;
    PVOID ObjectPointer;
    ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_ENTRY;

typedef struct {
    ULONG HandleCount;
    SYSTEM_HANDLE_ENTRY Handles[1];
} SYSTEM_HANDLE_INFORMATION;


BOOL OpenProcessEx(DWORD pid, HANDLE *ppv)
{
	BOOL success = FALSE;
	HMODULE ntdll = GetModuleHandle("ntdll");
	while (1)
	{
		CSRPID CsrGetProcessId = (CSRPID)GetProcAddress(ntdll, "CsrGetProcessId");
		NTQSI NtQuerySystemInformation = (NTQSI)GetProcAddress(ntdll, "NtQuerySystemInformation");

		if (!CsrGetProcessId || !NtQuerySystemInformation)
		{
			//MessageBox(0, TEXT("no api"),0,0);
			break;
		}
		// otwórz csrss.exe
		DWORD csrpid = CsrGetProcessId();
		HANDLE csrss = OpenProcess(PROCESS_DUP_HANDLE, FALSE, csrpid);
		if (!csrss)
		{
			//MessageBox(0, TEXT("Open csrss error"),0,0);
			break;
		}

		ULONG bsize = 32768;
		SYSTEM_HANDLE_INFORMATION *handles = (SYSTEM_HANDLE_INFORMATION*)malloc(bsize);
		DWORD status;
		while (handles)
		{
			ULONG cch;
			status = NtQuerySystemInformation(SystemHandleInformation, handles, bsize, &cch);
			if (!status || (status != 0xc0000004)) break;
			free(handles);
			bsize += 32768;
			handles = (SYSTEM_HANDLE_INFORMATION*)malloc(bsize);
		}

		if (!status && handles)
		{
			int i;
			for (i=0; i<handles->HandleCount; i++)
			{
				if (handles->Handles[i].OwnerPid == csrpid)
				{
					if (DuplicateHandle(csrss, (HANDLE)handles->Handles[i].HandleValue, GetCurrentProcess(),
						ppv, 0, FALSE, DUPLICATE_SAME_ACCESS))
					{
						if (GetProcessId(*ppv) == pid) // głupie ale łatwe
						{
							success = TRUE;
							break;
						}
						CloseHandle(*ppv);
					}
				}
			}
		}
		if (handles) free(handles);
		CloseHandle(csrss);
		break;
	}
	return success;
}

int main(void)
{
	TOKEN_PRIVILEGES tp;
	HANDLE hToken;
	OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
	tp.PrivilegeCount = 1;
	LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), 0, 0);
	CloseHandle(hToken);

	HANDLE hProcess;
	if (OpenProcessEx(wpisz_tutaj_pid, &hProcess))
	{
		MessageBox(0, TEXT("OK"),0,0);
		CloseHandle(hProcess);
	}
	else
	{
		MessageBox(0, TEXT("pid not found"),0,0);
	}
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1