Newsgroup: it.comp.programmare.win32
Titolo: DLL injection

Ho visto che alcuni programmi per ingannare i firewall iniettano del
codice nello spazio di indirizzo di un altro processo spacciandosi
quindi per questo ed ottenendo il permesso di uscire (pcaudit.exe per
esempio) .
Dal punto di vista della programmazione mi domandavo come fanno .

xnoise ha scritto:


i programmatori più inesperti semplicemente mettono il codice in una DLL e
la fanno caricare in qualche modo al processo target; quelli più accorti
invece usano VirtualAllocEx, WriteProcessMemory e CreateRemoteThread,
oppure (sui sistemi dove CreateRemoteThread non è implementata, cioè sui
sistemi non-NT) usano trucchi di questo genere: congelano momentaneamente
un thread qualsiasi del processo target (SuspendThread), ottengono il suo
contesto (GetThreadContext), se lo salvano da qualche parte, lo modificano
cambiando CS ed EIP opportunamente puntandoli a del codice accessibile dal
processo target, aggiornano il contesto (SetThreadContext), riesumano il
thread (ResumeThread), il quale esegue il codice diciamo così, di
"dirottamento", che però non può essere eseguito per sempre: a un certo
punto il thread dirottato dovrà pur riprendere il suo stato originale,
altrimenti il programma target non funziona più come ci si aspetta: e
dunque il programmatore accorto cosa fa, fa in modo che il "codice di
dirottamento" effettui una opportuna chiamata a CreateThread, dopodiché
riesumano il thread dirottato al suo stato originale ripristinando i
vecchi valori del contesto (XxxThreadContext), e a quel punto è fatta:
esiste un thread contenente codice iniettato "clandestinamente" che gira
nel contesto di un altro processo, e tutti gli altri threads continuano a
lavorare tranquillamente per conto loro.
tuttavia, dal momento che la gestione dei moduli sui sistemi non-NT *non
è* copy-on-write (cosa che ho scoperto recentemente), è possibile
utilizzare anche altri sistemi spesso più semplici: se si sa con certezza
che il processo target utilizza una certa chiamata API in determinate
situazioni, si può semplicemente installare una funzione di
intercettazione per quella API piazzando un JMP all'inizio del codice
della API stessa (per ulteriori dettagli, vedere la mia risposta al thread
"Monitorare le DLL e le chiamate"); in tal modo si ha che qualsiasi
processo chiami la funzione API dirottata, chiamerà anche la *tua*
funzione di intercettazione eseguendo il *tuo* codice nel contesto di *un
altro* processo; però chiaramente la tua funzione di intercettazione per
non trasformarsi in una ricetta di crash garantito deve essere accessibile
da *qualsiasi* processo, percui la puoi piazzare ad esempio in uno dei
buchi di kernel32.dll come fa Matt Pietrek.
a cosa si può applicare quest'ultimo sistema? be', ad esempio io posso (e
ricordo, *solo* su sistemi non-NT) con questo sistema intercettare tutte
le chiamate del sistema alla funzione socket oppure connect oppure send o
qualche altra compagna, in maniera tale da poter inviare dati esattamente
nei momenti in cui lo fa un altro programma che ha via libera ad Internet,
come ad esempio un browser o un programma di chat, così da non
insospettire non solo il firewall hardware o software che sia, ma nemmeno
l'utente, quale non noterà nessuna attività "strana"! oppure altrimenti
(soluzione forse più semplice, ma non sempre) sfruttare l'intercettazione
di una chiamata API che un normale programma Win32 effettua molto
frequentemente, come GetMessage, per creare un thread che lavori per conto
suo e possa inviare e ricevere dati quando gli pare.
poi considera anche che non è detto che tutto il baraccone debba
funzionare in user-mode: se l'utente target ha i privilegi di
administrator (come spesso accade) e ha la possibilità di installare
drivers, non dovrebbe essere difficile trovare un bug di IE (a parte che
ora sto notando che stanno saltando fuori dei bug abbastanza simpatici
pure in FF) che permettano il download e l'esecuzione di una procedura di
installazione di un network driver; se lo piazzi bene il firewall nemmeno
lo vede, a prescindere dal processo :D però di reti purtroppo non me ne
intendo molto, quindi qui non posso dirti + di tanto.
so solo che se vuoi un lavoro perfettamente pulito, un programma
completamente volatile ed invisibile, una vera maledizione insomma, devi
creare un driver che in fase di caricamento allochi un'area di memoria, ci
scriva il vero codice e fallisca il caricamento: in questo modo il driver
non sarà caricato e non potrà apparire non solo nell'elenco dei processi
del Task Manager o di qualsiasi altro programma analogo, ma nemmeno negli
elenchi dei programmi che listano i drivers caricati nel sistema! :D
insomma, di metodi per fare quello che dici ne esistono a bizzeffe, hai
solo che da scegliere, almeno per piattaforme Windows, poi non so come sia
la situazione su Linux, ma penso che esistano altri sistemi anche là; però
in fondo di Linux chisseneimporta, la pirateria mira soprattutto a
Windows, che è commercialmente più importante.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 "Monitorare le DLL e le chiamate"); [...]
su questa parte dimenticavo un importante dettaglio: "piazzare un JMP" non
č un'operazione atomica, perché si tratta di scrivere 5 bytes, quindi piů
di 4; di conseguenza devi prepararti anche all'evenienza che a causa del
multitasking/multithreading del SO un altro thread del sistema chiami la
funzione prima che tu abbia completato la scrittura del JMP: in tal caso
sarebbe crash garantito. per evitare il crash devi dividere l'operazione
in 3 fasi:
1) ti salvi da qualche parte i primi 5 bytes originali del codice della
funzione (ovviamente);
2) all'inizio della funzione scrivi una adeguata istruzione RET: se
conosci con esattezza il prototipo della funzione e le sue convenzioni di
chiamata, potrai mettere il RET giusto; spesso ad esempio le funzioni
ricevono tutti i parametri nello stack e si occupano loro stesse del
cleanup dello stack; sapendo questo e sapendo il numero complessivo di
bytes occupato dai parametri nello stack, dovrai mettere un'istruzione RET
N, dove N č appunto la dimensione complessiva in bytes dei parametri;
3) l'istruzione RET N occupa meno di 5 bytes, e ne occupa anche meno di 4
(per l'esattezza ne occupa 3 :D), quindi scriverla *č* un'operazione
atomica; la funzione dunque dopo la scrittura del RET risulta ancora
"funzionante" (per modo di dire: semplicemente in un piccolissimo istante
non farŕ nulla). a questo punto scrivi gli ultimi 2 bytes del JMP che devi
mettere (operazione atomica, la funzione funziona ancora grazie al RET),
ed infine scrivi i primi 3 bytes del JMP (sempre atomica, e il gioco č
fatto).
N.B.: nella seconda e terza fase ho sempre supposto che il RET occupasse 3
bytes, ma naturalmente questo puň occuparne anche uno solo se il prototipo
della funzione non usa la convenzione di chiamata __stdcall; in tal caso
non cambia nulla di sostanziale: dopo aver scritto il RET dovrai
semplicemente scrivere gli ultimi 4 bytes del JMP (anziché 2) che č sempre
un'operazione atomica, ma dal momento che c'č il RET in questo caso non
importerebbe se non lo fosse; infine dopo aver scritto gli ultimi 4 bytes
scrivi il 1° byte del JMP; insomma hai capito, no?.



Guarda che chicca ho trovato  :
Funziona alla grande solo che ho bisogno che mi confermi alcuni
assunti de me fatti :
1) La funzione avviata dal thread (BEM) gira nello spazio di indirizzo
di un altro processo , quindi qualsiasi riferimento a variabili e
funzioni nel processo chiamante generera un errore di memoria
protetta.
2) Non capisco perche la GetCommandLine debba essere caricata in quel
modo se Win32 mappa la funzione allo stesso indirizzo in tutti i
processi .
3) Cosa succede se termina il processo intercettato ?
Il thread viene terminato e il suo stato segnalato al processo
chiamante ?
4) Voglio disassemblare la funzione GetCommandLineW da Kernel32.dll .
Quale programma (nome) devo usare ?  Come procedo ?
ciao 
............ segue codice ................
#include "stdafx.h"
#define lenof(x) ( sizeof (x) / sizeof ((x)[0]) )
typedef const wchar_t *(__stdcall *tGCLW)( void );
const DWORD MAXINJECTSIZE = 4096;
struct Common
{
	DWORD gle; // last error from remote thread
	tGCLW pGCLW; // address of GetCommandLineW()
	wchar_t str[2000]; // the command line buffer
};
// try to enable SeDebugPrivilege
void EnableDebugPriv( void );
// inject function bem() into target process
bool Bugger( HANDLE h, wstring &str );
// and this is the code we are injecting
DWORD __stdcall bem( Common *c );
int wmain( int argc, wchar_t *argv[] )
{
	int i;
	DWORD pid;
	HANDLE h;
	wstring str;
	if ( argc == 1 )
	{
		wcout << endl << L"usage: remthread pid [pid ...]" <<
endl;
		wcout << L"Reports the command lines of the specified
processes." << endl;
		wcout << L"Use \"-1\" to have the program look at
itself." << endl;
		return 1;
	}
	EnableDebugPriv();
	for ( i = 1; i < argc; ++ i )
	{
		wstringstream( argv[i] ) >> pid;
		if ( pid == (DWORD) -1 )
			pid = GetCurrentProcessId();
		wcout << L"pid " << pid << L": ";
		h = OpenProcess( PROCESS_CREATE_THREAD |
PROCESS_VM_OPERATION |
			PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid
);
		if ( h != 0 )
		{
			if ( Bugger( h, str ) )
				wcout << endl << L"    \"" <<
str.c_str() << L"\"";
			CloseHandle( h );
			wcout << endl;
		}
		else
			wcout << L"open failed, gle = " <<
GetLastError() << endl;
	}
	return 0;
}
void EnableDebugPriv( void )
{
	HANDLE hToken;
	LUID sedebugnameValue;
	TOKEN_PRIVILEGES tkp;
	if ( ! OpenProcessToken( GetCurrentProcess(),
		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
	{
		wcout << L"OPT() failed, gle = " << GetLastError() <<
			L" SeDebugPrivilege is not available." <<
endl;
		return;
	}
	if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME,
&sedebugnameValue ) )
	{
		wcout << L"LPV() failed, gle = " << GetLastError() <<
			L" SeDebugPrivilege is not available." <<
endl;
		CloseHandle( hToken );
		return;
	}
	tkp.PrivilegeCount = 1;
	tkp.Privileges[0].Luid = sedebugnameValue;
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp,
NULL, NULL ) )
		wcout << L"ATP() failed, gle = " << GetLastError() <<
			L" SeDebugPrivilege is not available." <<
endl;
	CloseHandle( hToken );
}
bool Bugger( HANDLE h, wstring &str )
{
	HANDLE ht = 0;
	void *p = 0;
	Common *c = 0;
	bool result = false;
	DWORD rc;
	HMODULE hk32 = 0;
	Common localCopy;
	// allocate memory
	p = VirtualAllocEx( h, 0, MAXINJECTSIZE, MEM_COMMIT,
PAGE_EXECUTE_READWRITE );
	if ( p == 0 )
	{
		wcout << L"VAE() failed, gle = " << GetLastError();
		goto cleanup;
	}
	c = (Common *) VirtualAllocEx( h, 0, sizeof Common,
MEM_COMMIT, PAGE_READWRITE );
	if ( c == 0 )
	{
		wcout << L"VAE() failed, gle = " << GetLastError();
		goto cleanup;
	}
	// copy function there
	if ( ! WriteProcessMemory( h, p, &bem, MAXINJECTSIZE, 0 ) )
	{
		wcout << L"WPM() failed, gle = " << GetLastError();
		goto cleanup;
	}
	// initialize data area for remote guy
	hk32 = LoadLibrary( L"kernel32.dll" );
	if ( hk32 == 0 )
	{
		wcout << L"LL() failed, gle = " << GetLastError();
		goto cleanup;
	}
	localCopy.gle = 0;
	localCopy.pGCLW = (tGCLW) GetProcAddress( hk32,
"GetCommandLineW" );
	if ( localCopy.pGCLW == 0 )
	{
		wcout << L"GPA() failed, gle = " << GetLastError();
		goto cleanup;
	}
	FreeLibrary( hk32 );
	hk32 = 0;
	localCopy.str[0] = L'\0';
	if ( ! WriteProcessMemory( h, c, &localCopy, sizeof localCopy,
0 ) )
	{
		wcout << L"WPM() failed, gle = " << GetLastError();
		goto cleanup;
	}
	// CreateRemoteThread()
	ht = CreateRemoteThread( h, 0, 0, (DWORD (__stdcall *)( void
*)) p, c, 0, &rc );
	if ( ht == NULL )
	{
		wcout << L"CRT() failed, gle = " << GetLastError();
		goto cleanup;
	}
	rc = WaitForSingleObject( ht, 3000 );
	switch ( rc )
	{
	case WAIT_TIMEOUT:
		wcout << L"WFSO() timed out. Odd!";
		goto cleanup;
	case WAIT_FAILED:
		wcout << L"WFSO() failed, gle = " << GetLastError();
		goto cleanup;
	case WAIT_OBJECT_0:
		// this might just have worked, pick up the result!
		if ( ! ReadProcessMemory( h, c, &localCopy, sizeof
localCopy, 0 ) )
		{
			wcout << L"RPM() failed, gle = " <<
GetLastError();
			goto cleanup;
		}
		if ( localCopy.gle == 0 )
		{
			str = localCopy.str;
			result = true;
			wcout << L"successfully buggered.";
		}
		else
			wcout << L"Remote thread failed, gle = " <<
localCopy.gle;
		break;
	default:
		wcout << L"WFSO() returned a surprise! rc = " <<
			rc << L", gle = " << GetLastError();
		break;
	}
cleanup:
	CloseHandle( ht );
	if ( p != 0 )
		VirtualFreeEx( h, p, 0, MEM_RELEASE );
	if ( c != 0 )
		VirtualFreeEx( h, c, 0, MEM_RELEASE );
	if ( hk32 != 0 )
		FreeLibrary( hk32 );
	return result;
}
// The whole shebang makes a number of assumptions:
// -- target process is a Win32 process
// -- kernel32.dll loaded at same address in each process (safe)
// -- bem() shorter than MAXINJECTSIZE
// -- bem() does not rely on the C/C++ runtime
// -- /GZ is _not_ used. (If it is, the compiler generates calls
//    to functions which are not injected into the target. Oops!
DWORD __stdcall bem( Common *c )
{
	const wchar_t *src;
	wchar_t *tgt, *end;
	// __asm int 3;
	src = c->pGCLW();
	tgt = &c->str[0];
	end = &c->str[lenof( c->str ) - 1];
	if ( src == 0 || tgt == 0 || end == 0 )
	{
		c->gle = 998;
		return 0;
	}
	for ( ;	*src != L'\0' && tgt < end; ++ src, ++ tgt )
		*tgt = *src;
	*tgt = L'\0';
	c->gle = 0;
	return 0;
}

 Quale programma (nome) devo usare ?  Come procedo ?
un disassemblatore o un comune debugger; come disassemblatore ho sentito
parlare molto spesso del SoftIce, mentre se ti basta un debugger
semplicemente entra nella funzione facendo il debug col VC++.
ciao


 [CUT... un sacco di cose interessanti]
Complimenti, mrnt!!
Anche se sono ignorante in queste materie, tali argomenti e tecniche mi 
hanno sempre affascinato. Potrei chiederti se avresti dei testi cartacei 
o URL da consigliare ove trovare informazioni sulla programmazione "di 
sistema" cosi' avanzate? 
Ciao e grazie per eventuali consigli,
Dan

stesso; 
Si pero' ho notato che se non faccio in quel modo e chiamo la
GetCommandLine direttamente ottengo un errore di protezione e non
capisco perche' richiamandola attraverso la Common
src = c->pGCLW();
 invece funziona correttamente visto che l'indirizzo E' riferito
sempre al processo chiamante .

 Ciao e grazie per eventuali consigli,
ciao


 sempre al processo chiamante .
se nel codice da iniettare nel processo remoto chiami una API direttamente
anziché usando un puntatore alla stessa, ottieni un errore perché come ti
ho detto il codice generato dal compilatore non chiama direttamente la
API, chiama un'istruzione che è rimasta nel processo originale (non l'hai
copiata nel processo target assieme alla BEM, e non potresti neanche farlo
perché chissà dove sta!) che è un JMP alla API vera e propria.
inizialmente credevo (ad intuito) che disabilitando /GZ il compilatore
eliminasse quei JMP intermedi, poi invece controllando in MSDN ho visto
che avevo toppato. :P


che avevo toppato. :P
Ho visto il codice assembler all'interno del debugger di Visual C++ e
le chiamate alla GetCommandLineW avvengono in maniera tradizionale
usando una CALL e non una JUMP 
quindi non riesco a capire come mai se richiamo la GetCommandLineW
nella BEM mi da un errore di protezione .

nella BEM mi da un errore di protezione .
Mi rispondo da solo .
La BEM e' chiamata nello spazio di indirizzo di un altro processo e la
Common e' definita nello stesso spazio di indirizzo anche se
l'indirizzo reale della GetCommandLineW e' uguale in entrambi i
processi.
Solo che se la chiamo direttamente all'interno della BEM il
compilatore in qualche modo genera istruzioni di chiamata all'interno
del processo chiamante e questo provoca un errore di memoria protetta.

 nella BEM mi da un errore di protezione .
uffaaaaa, non so se a te funziona alla stessa maniera, ma se io faccio un
programma Win32 che chiama una API il compilatore genera si un CALL, ma
questo CALL chiama un pezzo di codice contenente un JMP all'API, e questo
pezzo di codice non č contenuto nella BEM, sta ad un indirizzo che č
valido solo nel contesto del processo chiamante! senza contare il _chkesp
finale, perņ quello vale solo per la modalitą Debug.


 del processo chiamante e questo provoca un errore di memoria protetta.
.. eh? O_o


> [...]
Minchia.....
ma dove le hai imparate tutte ste cose?
Ho avuto lo stesso istinto di quel giorno che mentre imparavo a
suonare la chitarra ho visto suonare Pat Metheny. 
Ho venduto la mia.

 Ho venduto la mia.
asd e pensa che io ho solo 19 anni... certo, molte volte ho avuto anche io
questa sensazione, perfettamente normale considerando che c'è *sempre*
qualcuno più forte! però io non mi sono lasciato scoraggiare, sono sempre
stato affascinato dalla materia, e poi spesso la mia consolazione è stata:
"cavolo, quello è un mostro vabbè, però io non sono nemmeno un
professionista, pure troppo che ne so, al liceo ero circondato dai peggio
niubbi!!!" :P
l'unica persona che certe volte è riuscita a mettere in difficoltà anche
questa mia poca certezza è stata Juliet, che ho intuito essere molto
giovane (ho letto alcuni suoi vecchi post su it.comp.programmare.*, era
principalmente quello a cui mi riferivo quando parlavo a Danguard di
"googlate su Usenet").



Ho letto tutte le altre cose che hai scritto, ma sempre la stessa storia...
"Scrivere un JMP nella routine"...bè, o sei il sistema operativo, o non lo 
fai!!! O almeno in teoria DEVE essere così.
Le cose che hai scritto sono interessanti, ma bisogna avere i privilegi 
kernel di esecuzione del codice o mi sto sbagliando?
Ciao
Giovanni.

 fai!!! O almeno in teoria DEVE essere così.
e invece lo fai! perché mai non potresti? si tratta semplicemente di
scrivere ad un certo indirizzo di memoria (indirizzo perfettamente valido
nel contesto del tuo processo), oppure di utilizzare la
WriteProcessMemory; devi solo avere l'accortezza di cambiare le modalità
di protezione della pagina con VirtualProtect.
ribadisco: leggiti in MSDN la descrizione di quelle API.
aggiungo che ovviamente l'unico requisito per poter fare tutti questi
casini sugli altri processi è avere la possibilità di aprire un HANDLE
valido e con diritti sufficienti; la OpenProcess potrebbe negarti certi
permessi quando la chiami da un processo che gira nel contesto di
sicurezza di un user con permessi ristretti, ad esempio normalmente se sei
su un account Administrator OpenProcess nega l'accesso ai processi SYSTEM
(a meno che non abiliti il privilegio SE_DEBUG_NAME vabbè; se vuoi evitare
anche quello devi regolare bene la policy credo). tuttavia ti svelerò 1
piccolo segreto: *stando alle mie conoscenze* (il che significa che non
sono del tutto sicuro ma c'è una buona probabilità) nei kernel NT-based
puoi avere accesso a *qualsiasi* processo con tutti i permessi che vuoi
utilizzando le API native, e precisamente la NtOpenProcess; non l'ho
provata ancora, ma un giorno lo farò senz'altro perché m'incuriosisce
assai :P
intanto guardati questo bel sitarello:
http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/
bellino, eh? :) ma in particolare guardati questa:
http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Process/NtOpenProcess.html
per l'esattezza si trova in "NT Objects/Process"
ciao


 [...] (e bada bene: si fa TUTTO IN USER MODE!) [...]
l'unico caso in cui con questi sistemi ti ritrovi ad eseguire codice
kernel mode è quando intercetti una chiamata ad una funzione kernel mode
:PPP
espediente che può avere anch'esso la sua utilità :)
ariciao


 ha scritto nel messaggio 
news:d49cj8$t8p$1...@news.newsland.it...
[CUT]
Ciao,
se hai provato e funziona allora non so che pensare.
Non conosco in dettaglio il sistema windows, ma, secondo le caratteristiche 
che un sistema operativo dovrebbe offrire, tra queste c'è la sicurezza e, 
come ne parli tu, sembra che vada tutto a pu***ne.
In user mode non puoi assolutamente andare a scrivere in un'area di memoria 
diversa dal contesto del tuo programma (e intendo solo l'area dati...in 
teoria non potresti nemmeno modificare il tuo codice).
Figurati poi creare un thread all'interno di un programma estraneo al tuo!
Quando dici che devi avere l'handle e i diritti sufficienti, a parte che non 
mi sembra poco, e poi cmq questo prevede che tu stia eseguendo già del 
codice sulla macchina ospite!!!
Mi sembra una cosa ridicola, ma se hai provato e funziona non ho nulla da 
ridire...d'altronde ti ripeto, non conosco affatto il sistema windows!
Mi sembra solamente strano che si possano fare tutte queste cose, niente di 
che!
Cmq sia non volevo mettere in dubbio ciò che è stato provato :) , 
semplicemente volevo riferire le mie perplessità in merito.
Mi sembra solamente strano che si possano modificare i contesti dei thread a 
proprio piacimento...dovrebbe essere una cosa che fa solo ed esclusivamente 
il sistema operativo....bo!!!!
Ciao ciao. 

 Ciao ciao.



[CUT]
Pensavo da remoto perchè il post di xnoise parlava di ingannare firewall 
ecc...
Ecco perchè c'era quella cosa che mi sfuggiva e non mi quadrava del tutto :) 
...mi sembrava un'assurdità...eh!eh! :P
Cmq sia, sui debbuger...bè, un processo che modifica l'area dati di un altro 
processo è una cosa assolutamente da vietare, altrimenti tutti i processi si 
vanno a sfottere uno con l'altro e succederebbe un macello.
Per quanto riguarda il debug, che io sappia, quando il debbugger lancia il 
tuo programma, questo viene eseguito in modo particolare dal uP e 
all'interno del codice vengono inserite le istruzioni di debug che ti 
permettono di fare tutto quello che fai! Quindi non è il Visual Studio che 
ti cambia le variabili del tuo processo, ma il processo stesso! :-)
Questo è quanto so, ma potrei anche sbagliarmi...ancora non mi sono 
documentato a fondo su queste cose...!
Cmq la poca chiarezza era dovuta al fatto che credevo che facessi tutto 
questo da remoto.
Ecco perchè t'avevo chiesto di farmi luce sul: "si ok!, tutto quello che 
vuoi, ma PRIMA di fare tutto ciò, come faccio ad eseguire codice per poi 
ottenere l'handle, ecc. ecc. ?" :)
In effetti sei partito con il presupposto di far girare un programma già 
sulla macchina ospite...
...adesso tutto quadra! :P
Ciao ciao. 

 Ciao ciao.
cia'


 assai :P
ehm, poco fa ho provato ad usare la NtOpenProcess e a fare qualche
esperimento provando ad accedere a winlogon.exe e svchost.exe, ma mi ha
risposto ciccia ^_^
temo che in linea teorica non si possa accedere a processi di altri utenti
:P
e bravo il signor Guglielmino Cancelli: il sistema di sicurezza č ben
radicato, eh? be' chissene frega, tanto all'occorrenza esiste anche
qualche simpatico exploit per rimediare all'inconveniente :)
il subsystem Win32 ha un paio di errori di design exploitabili; conosco un
exploit di cui esistono due versioni: una č per le Edit Box, perņ l'autore
dev'essere un gran co*****e perché l'exploit manda in crash il processo
target (errore nello stack, incompatibilitą di prototipi di funzioni) e
l'autore non ne capisce il motivo asd :D (dice che nelle prove che ha
fatto con IE gli crashava solo a volte; evidentemente IE cattura
l'eccezione, ma la maggior parte dei programmi non lo fanno :P )
l'altra versione invece dev'essere decisamente migliore: riguardava i
messaggi WM_TIMER, ma non ne conosco bene il funzionamento (di questa
versione, non dei timers), dovrei riguardarmela.
comunque penso che la prima versione sia sufficiente: infatti basta
eseguire tutto il codice necessario *prima* del crash del processo target
(magari solo lo stretto indispensabile) e dopo il crash kissene; al prox
riavvio il pc dovrebbe essere stato adeguatamente "sistemato".
