View Full Version : CS:EIP
Salve a tutto il forum :p
Volevo avere un'informazione di basso livello, diciamo così: in che modo funzionano esattamente i registri CS ed EIP in modalità protetta? Sono sempre gli unici due implicati nella memorizzazione dell'indirizzo dell'istruzione corrente? In che modo devono essere combinati per ottenere questo indirizzo? Cioè, cosa vuol dire esattamente la dicitura "CS:EIP"? Quello che non capisco è che il registro EIP è già a 32 bit (se non sbaglio...) e quindi da solo dovrebbe essere sufficiente a descrivere un indirizzo di memoria... Non c'è una ridondanza di contenuto tra i due registri?
Per essere più specifico, vi dirò esattamente quello che mi interessava fare: lavoro in C su Windows, e ciò che volevo fare è dirottare un thread di cui ho un handle con tutti i permessi necessari, cioè:
1) sospenderlo con la SuspendThread;
2) ottenere i registri del suo contesto con GetThreadContext; la struttura risultante dovrebbe contenere tra le altre cose anche CS ed EIP; inoltre è molto importante che contenga anche uno dei 4 registri general-purpose, EAX andrebbe benissimo;
3) salvarmi da qualche parte i valori dei registri CS, EIP ed EAX e riscriverli con valori miei in modo tale che il thread, appena riesumato, vada ad eseguire un'istruzione da me stabilita;
4) settare il nuovo contesto del thread da me modificato con la SetThreadContext;
5) riesumare il thread con ResumeThread, il quale a questo punto andrà ad eseguire il codice da me stabilito.
Nota bene: il codice da me stabilito contiene alla fine una chiamata a SuspendThread, in modo tale che il thread viene nuovamente sospeso alla fine e io ho il tempo di ripristinare i valori originali di CS, EIP ed EAX.
Tutto cio' è possibile secondo voi?
Grazie
Una precisazione: è possibile che quando faccio tutto il casino il thread si trovi in realtà in kernel mode, non in user mode, ma sempre in modalità protetta.
AnonimoVeneziano
17-02-2005, 09:21
CS è un registro a 16 bit chiamato "Code Segment" .
Specifica il segmento di memoria dove risiede il codice da eseguire (ossia le istruzioni macchina del programma in esecuzione) .
In modalità protetta flat tutti i registri segmento (CS , DS, SS, ES, FS, GS) puntano nello stesso punto , ossia l'inizio della memoria e poi viene usato un OFFSET a 32 bit per spaziare dal byte 0 al byte 2^32 -1 .
Nel Registro EIP c'è l'indirizzo di memoria della prossima istruzione ad essere eseguita e semplicemente ne contiene l'OFFSET dall'inizio della memoria
In modalità reale (dove si usa maggiormente il modello di memoria Segmented) il registro CS si combina col registro IP (la controparte a 16 bit di EIP) creando un indirizzo a 20 bit che punta alla memoria dove è contenuta la prossima istruzione da eseguire .
La dicitura CS:IP o CS:EIP è un cosìddetto "far pointer" , ossia un indirizzo di memoria composto da Segment Selector (CS) e da offset (IP o EIP) . Il processore combina automaticamente questi due valori creando un indirizzo lineare che si riferisce all' area di memoria alla quale vogliamo accedere . Se ti interessa di + l'argomento e come il processore converte gli indirizzi ti consiglio di leggerti qualcosa sulla memoria segmentata nei processori x86 :)
Per quanto riguarda il voler modificare EIP , pur non conoscendo le funzioni C che hai elencato dato che programmo per lo + sotto Linux, so che EIP non è direttamente modificabile via software , ma gli unici modi per modificarlo è usare istruzioni assembly come "JMP , Jcc, CALL , RET" oppure far verificare Interrupts o Exceptions che fanno alterare il corso di esecuzione del programma. Un metodo (tramite assembly) per dare ad EIP il valore che si vuole potrebbe essere quello di usare una CALL per memorizzare il valore di EIP nello stack , modificare il valore memorizzato nello stack, che è l'indirizzo dell' istruzione dopo la CALL, a proprio piacimento e usare "RET" per impostare EIP.
Non so se le funzioni che hai elencato in qualche modo usino qualche procedimento del genere per impostare EIP , ma se non lo fanno di sicuro non toccano EIP
Ciao
Innanzitutto grazie per la spiegazione, mi hai fatto capire varie cose, ma ho alcune domande: cosa intendi esattamente quando dici che i registri di segmento puntano tutti all'inizio della memoria? Quale sarebbe l'inizio? L'inizio della memoria dedicata al processo o proprio l'inizio nel senso "indirizzo fisico 0"?
E poi sei proprio sicuro che non si possa in alcun modo modificare il contenuto di EIP via software in maniera diretta? Nessuna delle varianti dell'istruzione MOV funziona con EIP come destinazione?
Comunque sia, se io imposto a mio piacere la struttura CONTEXT e chiamo SetThreadContext (ammesso che il mio programma abbia tutti i permessi necessari per farlo) io mi aspetto che il tutto funzioni, no? Se EIP non si può proprio modificare via software, allora probabilmente Windows quando deve modificare il contesto del thread effettua un qualche meccanismo tipo quello che hai descritto prima.
Ma quindi ammettendo che la SetThreadContext funzioni come mi aspetto, secondo te il tutto può funzionare?
Ti ringrazio per l'attenzione. :)
PS: una cosa che non ho specificato nei post precedenti è che il thread non è mio, nel senso che si trova in un altro processo e quindi il codice che esegue non l'ho creato io, quindi non posso mettere in quel thread tutti i CALL che mi pare; il codice sul quale "dirottare" il thread invece lo scelgo io perché lo scrivo manualmente nel processo con VirtualAllocEx e WriteProcessMemory.
PPS: tutte queste funzioni che nomino non sono funzioni standard del C, fanno parte delle interfacce API di Windows, più precisamente del subsystem Win32; probabilmente non ne conosci nessuna visto che lavori su linux :p
Ciao
AnonimoVeneziano
17-02-2005, 15:19
Quando dico che punta all' inizio della memoria intendo del sistema, non quella specifica del programma.
Non sono certo che i registri puntino proprio a 0 , credo dipenda anche da come li gestisce il SO , comunque puntano in una zona prossima allo 0 nella memoria .
Come ti ho già detto nessuna istruzione Assembly (ed in particolare la MOV) agisce sul registro EIP , tranne quelle che ti ho indicato io prima, e comunque non saresti in grado comunque di modificarlo direttamente (infatti devi usare un trucchetto come quello che ti ho descritto) . Comunque non conoscendo le funzioni che hai elencato non posso sapere se funzionino o no, l'unico consiglio che ti posso dare è di provare :)
Ciao
Ok, ma quindi se ho ben capito in modalità protetta per descrivere l'indirizzo dell'istruzione corrente non serve CS è sufficiente EIP? E questo indipendentemente se sono in kernel o user mode? Cioè, CS punta sempre allo stesso indirizzo fisico (prossimo allo 0) per qualsiasi processo e per qualsiasi thread?
Per quanto riguarda il fare delle prove, a dir la verità non so se e quando realizzerò tutto il baraccone, in quanto ciò che io voglio fare esattamente è eseguire del codice invisibile su un computer su cui sono certo che è installato Windows; ora, sui sistemi NT-based, esiste una certa funzione, la CreateRemoteThread, che mi permette di risolvere il problema in maniera relativamente facile, ma la stessa funzione sui sistemi win9x non è implementata, e il computer target non so che versione abbia di Windows :mc:: se ha Windows 98 o Me la CreateRemoteThread non funzionerà, e io sarò costretto ad implementare quest'altro sistema del "thread-hijacking", chiamiamolo così.
Per ora mi sono voluto informare sulla questione per pura sete di cultura informatica. :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.